merge conflicts

master
wangning 7 years ago
commit ca23d42860

@ -361,3 +361,108 @@ ADD COLUMN `surcharge_cashback` decimal(10,4) default 0 after `royalpay_surcharg
ALTER TABLE sys_clients ADD store_photo VARCHAR(200) NULL;
CREATE TABLE `log_client_sub_merchant_id` (
`id` varchar(50) NOT NULL,
`sub_merchant_id_before` varchar(30) DEFAULT NULL COMMENT '修改之前的sub_merchant_id',
`sub_merchant_id_after` varchar(30) NOT NULL COMMENT '修改之后的sub_merchant_id',
`operator` varchar(30) NOT NULL COMMENT '操作人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`client_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `pmt_sub_merchant_id` (
`sub_merchant_id` varchar(30) NOT NULL,
`merchant_id` varchar(30) NOT NULL,
`is_valid` tinyint(1) DEFAULT 1,
`operator` varchar(30) DEFAULT '',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`sub_merchant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
alter table sys_clients add column common_sub_merchant_id tinyint(1) default 0 comment '是否使用通用子商户号';
CREATE TABLE `cli_sub_merchant_id` (
`sub_merchant_id` varchar(30) NOT NULL,
`merchant_id` varchar(30) DEFAULT NULL,
`client_count` int(8) DEFAULT NULL,
`temp_sub_merchant` tinyint(1) DEFAULT 0,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`sub_merchant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `sys_clients` ADD COLUMN `business_hours` varchar(100) DEFAULT '';
ALTER TABLE `sys_clients` ADD COLUMN `merchant_introduction` varchar(500) DEFAULT '';
ALTER TABLE `sys_clients` ADD COLUMN `merchant_tag` varchar(100) DEFAULT '';
ALTER TABLE `sys_clients` ADD COLUMN `merchant_video_url` varchar(200) DEFAULT '';
create table risk_merchant_record(
id varchar(50) not null comment 'id',
create_time datetime not null comment '创建时间',
expiry_time datetime not null comment '过期时间',
client_id int(11) not null comment '商户id',
client_moniker varchar(20) not null comment '商户code',
status varchar(5) not null comment '记录状态 0:未处理,1已处理,2处理中',
risk_types varchar(50) not null comment '触发的风控类型 "," 号分割',
risk_counts varchar(70) null comment '对应类型触发次数 "," 号分割',
primary key(id),
key(client_id) using BTREE
);
create table risk_white_list(
client_id int(11) not null comment '商户id',
client_moniker varchar(20) not null comment '商户code',
create_time datetime not null comment '创建时间',
is_valid TINYINT(1) DEFAULT 1 COMMENT '是否可用',
primary key(client_id),
key(client_id) USING BTREE,
key(client_moniker)
);
create table risk_merchant_detail_log(
id varchar(50) not null comment 'id',
record_id varchar(50) not null comment '商户风控记录id',
create_time datetime not null comment '创建时间',
client_id int(11) not null comment '商户id',
auditor varchar(30) not null comment '操作者',
auditor_id varchar(50) not null comment '操作者id',
files varchar(500) null comment '上传附件 "," 号分割',
remark varchar(100) null comment '备注',
primary key(id),
key(client_id) using BTREE,
key(record_id)
);
create table risk_transaction_log(
id varchar(50) not null comment 'id',
order_id varchar(500) not null comment '问题订单id',
record_id varchar(50) not null comment '商户风控记录id',
amount DECIMAL(10,2) not null comment '过期时间',
channel varchar(15) NULL COMMENT '订单支付通道',
client_id int(11) not null comment '商户id',
risk_types varchar(50) not null comment '触发的风控类型 ","号分割 ',
create_time datetime not null,
primary key(id),
key(order_id),
key(record_id),
key(client_id)
);
insert into `royalpay_production`.`sys_configs` ( `config_key`, `config_value`) values ( 'risk_counts', '3');
insert into `royalpay_production`.`sys_configs` ( `config_key`, `config_value`) values ( 'risk_total_amout', '5000');

@ -756,12 +756,12 @@
*
*/
/**
* @api {PUT} /api/v1.0/alipay/partners/{partner_code}/app_orders/{order_id} 创建支付宝SDK订单
* @apiName AlipaySDK
* @api {PUT} /api/v1.0/gateway/partners/{partner_code}/app_orders/{order_id} 创建SDK订单
* @apiName SDK
* @apiDescription
* 用于移动端APP调用支付宝SDK支付调用API创建订单得到支付宝SDK调用参数将参数传递给SDK拉起支付宝支付并由支付宝客户端直接返回支付结果
* 用于移动端APP调用微信SDK支付调用API创建订单得到微信SDK调用参数将参数传递给SDK拉起微信支付并由微信客户端直接返回支付结果
* <b>强烈建议获得支付结果后再调用RoyalPay订单查询API确认完成支付后再进行后续流程避免因超时自动撤单导致资金损失</b><br>
* <img src="img/sdk_api_payment.jpg"><br>
* <img src="img/sdk_wechat_api_payment_cn.png"><br>
* 关于客户端和支付宝整合的更多信息: <a href="https://global.alipay.com/service/app_split_cn/6">支付宝SDK文档</a><br>
* <a href="resources/api/alipaySdk-20160825.jar">SDK for Android</a><br>
* <a href="resources/api/AlipaySDKForiOS.zip">SDK for iOS</a>
@ -776,10 +776,12 @@
* @apiParam (JSON) {String} description 必填订单标题最大长度128字符超出自动截取
* @apiParam (JSON) {int} price 必填金额单位为货币最小单位例如使用100表示AUD1.00
* @apiParam (JSON) {String=AUD,CNY} currency=AUD 币种代码
* @apiParam (JSON) {String=Alipay,Wechat} channel 支付渠道必填大小写敏感
* @apiParam (JSON) {String} notify_url 支付通知url详见支付通知api不填则不会推送支付通知
* @apiParam (JSON) {String} operator 操作人员标识
* @apiParam (JSON) {String=android,iphone,ipad} system 客户端操作系统类型可选参数
* @apiParam (JSON) {String} version 客户端版本号可选参数
* @apiParam (JSON) {String=android,iphone,ipad} system 客户端操作系统类型支付宝通道可选微信不需要
* @apiParam (JSON) {String} version 客户端版本号支付宝通道可选微信不需要
* @apiParam (JSON) {String} appid 微信 appid微信通道要求必填
*
* @apiSuccess {String} return_code 执行结果
* @apiSuccess {String} result_code SUCCESS表示创建订单成功EXISTS表示订单已存在

@ -32,8 +32,8 @@
## 支付宝渠道区分
支付宝根据调用接口不同分为线上和线下两个渠道,两个渠道分别使用不同的汇率和手续费费率,为避免混淆在此区分:
+ 线上渠道包含H5 Mobile、Web支付以及APP SDK三种支付方式
+ 线下渠道:包含JSAPI、QR Code、Retail Pay 3种支付方式
+ 线上渠道包含H5 Mobile、Web支付、APP SDK、JSAPI、QR Code 5种支付方式
+ 线下渠道Retail Pay 支付方式
相似接口区别
- JSAPI和H5 MobileJSAPI只能在支付宝客户端内访问的页面调起支付H5可以在移动设备任意浏览器或App的WebView调起支付

@ -769,13 +769,14 @@
* @apiError (ERROR_CODE) ORDER_PAID Order has already been paid
*
*/
/**
* @api {PUT} /api/v1.0/alipay/partners/{partner_code}/app_orders/{order_id} 创建支付宝SDK订单
* @apiName AlipaySDK
* @api {PUT} /api/v1.0/gateway/partners/{partner_code}/app_orders/{order_id} Create SDK Order
* @apiName SDK
* @apiDescription
* Used for mobile Apps calling Alipay payment with Alipay SDK. Call this api to create order and get param string for SDK calling. Call SDK api with the param to start payment and get payment result from Alipay app
* Used for mobile Apps calling Wechat payment with Wechat SDK. Call this api to create order and get param string for SDK calling. Call SDK api with the param to start payment and get payment result from Wechat app
* <b>It is strongly advised to request RoyalPay order query Api to confirm that the order has been paid in order to cancelling order by system at the same time.</b><br>
* <img src="img/sdk_api_payment.jpg"><br>
* <img src="img/sdk_wechat_api_payment_en.png"><br>
* More information for integration with Alipay: <a href="https://global.alipay.com/service/app_split/6">Alipay SDK Document</a><br>
* <a href="resources/api/alipaySdk-20160825.jar">SDK for Android</a><br>
* <a href="resources/api/AlipaySDKForiOS.zip">SDK for iOS</a>
@ -789,10 +790,12 @@
* @apiParam (JSON) {String} description Required, Order description
* @apiParam (JSON) {int} price Required, Price of the order. Use the base unit of the currency.
* @apiParam (JSON) {String=AUD,CNY} currency=AUD Currency
* @apiParam (JSON) {String=Alipay,Wechat} channel payment channel, required, case sensitive
* @apiParam (JSON) {String} notify_url System will call the notify url if provided when the payment succeeds
* @apiParam (JSON) {String} operator Note for the operator who created this order.
* @apiParam (JSON) {String=android,iphone,ipad} system os type of client app, optional
* @apiParam (JSON) {String} version client app version, optional
* @apiParam (JSON) {String=android,iphone,ipad} system os type of client app, optional for Alipay, not required for Wechat
* @apiParam (JSON) {String} version client app version, optional for Alipay, not required for Wechat
* @apiParam (JSON) {String} appid wechat appid, required for Wechat, not required for Alipay
*
* @apiSuccess {String} return_code Execution result
* @apiSuccess {String} result_code SUCCESS means order created successfully, EXISTS means order has already existed.

@ -37,8 +37,8 @@ System error message supports Simplified Chinese and English. The system by defa
## Alipay Channels
According to different Api used, Alipay channel was distributed to Retail channel and Online channel. Two channels has different exchange rate and surcharge rate.
+ Online Channel: Including H5 Mobile, Online Payment and APP SDK
+ Retail Channel: Including JSAPI, QR Code Api, Retail Pay
+ Online Channel: Including H5 Mobile, Online Payment, APP SDK, JSAPI and QR Code Api
+ Retail Channel: Including Retail Pay
Difference
- JSAPI and H5 Mobile: JSAPI can only be called in the web page opened in Alipay Client. H5 Mobile can call the payment panel in any browser or webview in App in the mobile device.

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

@ -11,6 +11,9 @@ import java.util.List;
*/
public interface DashboardService {
JSONObject getCommonAnalysis1(JSONObject params);
JSONObject getCommonAnalysis3(JSONObject params);
JSONObject getCommonAnalysis2(JSONObject params);
// JSONObject getCommonAnalysis(JSONObject params);

@ -65,9 +65,9 @@ public class DashboardServiceImpl implements DashboardService,DashboardAnalysisT
@Override
public JSONObject getCommonAnalysis1(JSONObject params) {
JSONObject res = transactionAnalysisMapper.getClientTransaction(params);
res.put("new_partners", clientAnalysisMapper.countNewClients(params));
res.put("total_partners", clientAnalysisMapper.countClients(params));
res.put("traded_partners", clientAnalysisMapper.countTradedPartners(params));
// res.put("new_partners", clientAnalysisMapper.countNewClients(params));
// res.put("total_partners", clientAnalysisMapper.countClients(params));
// res.put("traded_partners", clientAnalysisMapper.countTradedPartners(params));
// List<JSONObject> topOrders = transactionAnalysisMapper.getTopOrders(params, new PageBounds(1, 1, Order.formString("aud_fee.desc")));
// if (!topOrders.isEmpty()) {
// res.put("top_amount_order", topOrders.get(0));
@ -77,6 +77,16 @@ public class DashboardServiceImpl implements DashboardService,DashboardAnalysisT
// res.put("old_customers", transactionAnalysisMapper.countOldCustomers(params));
return res;
}
@Override
public JSONObject getCommonAnalysis3(JSONObject params) {
JSONObject res = new JSONObject();
res.put("new_partners", clientAnalysisMapper.countNewClients(params));
res.put("total_partners", clientAnalysisMapper.countClients(params));
res.put("traded_partners", clientAnalysisMapper.countTradedPartners(params));
return res;
}
@Override
public JSONObject getCommonAnalysis2(JSONObject params) {
JSONObject res = new JSONObject();

@ -6,6 +6,7 @@ import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -32,4 +33,6 @@ public interface ClientAnalysisMapper {
List<JSONObject> listPartnersTradeAmount(JSONObject params, PageBounds pageBounds);
List<JSONObject> countClientsTypes(JSONObject params);
List<JSONObject> notTradeSubMerchantId();
}

@ -36,6 +36,13 @@ public class DashboardController {
return dashboardService.getCommonAnalysis1(params);
}
@ManagerMapping("/common_analysis_3")
public JSONObject commonAnalysis3(AnalysisBean analysis, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
JSONObject params = analysis.toParams(null);
orgManager.checkOrg(manager,params);
return dashboardService.getCommonAnalysis3(params);
}
@ManagerMapping("/common_analysis_2")
public JSONObject commonAnalysis2(AnalysisBean analysis, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
JSONObject params = analysis.toParams(null);

@ -26,6 +26,7 @@ public class AppQueryBean {
private OrderStatus status = OrderStatus.ALL;
private PayChannel channel = PayChannel.ALL;
private int[] gateway;
private int clearing_status=-1;
private String gateway_app;
private int page = 1;
private int limit = 20;
@ -86,6 +87,9 @@ public class AppQueryBean {
if (app_client_ids != null && !app_client_ids.isEmpty()) {
params.put("client_ids", app_client_ids.split(","));
}
if (clearing_status != -1) {
params.put("clearing_status", clearing_status);
}
return params;
}
@ -169,4 +173,12 @@ public class AppQueryBean {
public void setChannel(PayChannel channel) {
this.channel = channel;
}
public int getClearing_status() {
return clearing_status;
}
public void setClearing_status(int clearing_status) {
this.clearing_status = clearing_status;
}
}

@ -13,6 +13,7 @@ import com.alibaba.fastjson.JSONObject;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
@ -130,4 +131,6 @@ public interface RetailAppService {
JSONObject getInvoiceData(JSONObject device, AppQueryBean appQueryBean) throws Exception;
void getInvoiceFile(JSONObject device, AppQueryBean appQueryBean, HttpServletResponse httpResponse) throws Exception;
Map<String,JSONObject> channelAndDayOfAnalysis(int client_id, String clearingDetailId, String channel, JSONObject device);
}

@ -10,6 +10,7 @@ import au.com.royalpay.payment.manage.appclient.core.RetailAppService;
import au.com.royalpay.payment.manage.cashback.core.CashbackService;
import au.com.royalpay.payment.manage.customers.core.CouponValidateService;
import au.com.royalpay.payment.manage.fund.core.impls.XPlanFundConfigServiceImpl;
import au.com.royalpay.payment.manage.management.clearing.core.CleanService;
import au.com.royalpay.payment.manage.mappers.log.AppMessageLogMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailAnalysisMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailMapper;
@ -152,8 +153,9 @@ public class RetailAppServiceImp implements RetailAppService {
@Resource
private LogSettleMailMapper logSettleMailMapper;
@Resource
private CleanService cleanService;
@Resource
private ClientConfigService clientConfigService;
private Map<String, AppMsgSender> senderMap = new HashMap<>();
@Resource
@ -285,7 +287,8 @@ public class RetailAppServiceImp implements RetailAppService {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
int client_id = device.getIntValue("client_id") ;
//JSONObject client = clientManager.getClientInfo(client_id);
JSONObject client = clientManager.getClientInfo(client_id);
device.put("client_moniker",client.getString("client_moniker"));
TradeLogQuery tradeLogQuery = new TradeLogQuery();
tradeLogQuery.setDatefrom(appQueryBean.getBegin());
tradeLogQuery.setDateto(appQueryBean.getEnd());
@ -296,6 +299,13 @@ public class RetailAppServiceImp implements RetailAppService {
tradeLogService.exportTransFlow(tradeLogQuery,device,httpResponse);
}
@Override
public Map<String, JSONObject> channelAndDayOfAnalysis(int client_id, String clearingDetailId, String channel, JSONObject device) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
return cleanService.channelAndDayOfAnalysis(client_id, clearingDetailId,channel,device.getJSONObject("client"));
}
@Override
public void updateClient(JSONObject device, AppClientBean appClientBean) {
String clientType = device.getString("client_type");

@ -15,7 +15,6 @@ import au.com.royalpay.payment.manage.settlement.core.ManualSettleSupport;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.core.SignInStatusManager;
import au.com.royalpay.payment.manage.system.core.ClientContractService;
import au.com.royalpay.payment.manage.tradelog.beans.TradeLogQuery;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.device.advise.AppClientController;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
@ -23,31 +22,22 @@ import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.http.HttpUtils;
import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig;
import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import static au.com.royalpay.payment.tools.CommonConsts.RETAIL_DEVICE;
/**
@ -137,6 +127,15 @@ public class RetailAppController {
return retailAppService.getTransactionLogsByClearingDetailId(device, clearing_detail_id, timezone);
}
@RequestMapping("/{client_id}/settlement_logs/{clearingDetailId}/analysis/{channel}")
public Map<String,JSONObject> channelAndDayOfAnalysis(@PathVariable int client_id, @PathVariable String clearingDetailId,
@PathVariable String channel,@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device) {
if ("all".equals(channel)){
channel = "null";
}
return retailAppService.channelAndDayOfAnalysis(client_id, clearingDetailId,channel,device);
}
/* 消息模块begin */
@RequestMapping(value = "/notice", method = RequestMethod.GET)
public JSONObject listNotices(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device, @RequestParam Map<String, Object> params) {

@ -178,7 +178,7 @@ public class CustomerImpressionServiceImpl implements CustomerImpressionService
clientCustomersMapper.updateAfterPaymentFinish(clientCustomerInfo);
}
} finally {
locker.unlock(customer_id);
locker.unlock(CUSTOMER_IMPRESSION_PREFIX+customer_id);
}
} catch (Exception e) {
logger.debug("Reduce Customer Impression Error Redis Value =" + redisValue, e);

@ -0,0 +1,24 @@
package au.com.royalpay.payment.manage.dev.web;
import com.alibaba.fastjson.JSONObject;
import com.maxmind.geoip.LookupService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping(value = "/dev/ip")
public class IPController {
@Resource
private LookupService lookupService;
@RequestMapping(value = "/{ipAddr}", method = RequestMethod.GET)
public String getIpInfo(@PathVariable String ipAddr) {
String city = lookupService.getLocation(ipAddr).city;
return city;
}
}

@ -5,7 +5,6 @@ import au.com.royalpay.payment.channels.bestpay.runtime.BestPayClient;
import au.com.royalpay.payment.channels.jd.runtime.JDClient;
import au.com.royalpay.payment.channels.wechat.runtime.WxPayClient;
import au.com.royalpay.payment.core.PaymentApi;
import au.com.royalpay.payment.core.PaymentChannelApi;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.core.exceptions.OrderNotExistsException;
import au.com.royalpay.payment.manage.analysis.core.PlatformClearService;
@ -20,19 +19,21 @@ import au.com.royalpay.payment.manage.mappers.payment.RefundMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientBankAccountMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.manage.tradelog.core.TradeLogService;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.defines.TradeType;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.http.HttpUtils;
import au.com.royalpay.payment.tools.merchants.core.MerchantInfoProvider;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.utils.PdfUtils;
import au.com.royalpay.payment.tools.utils.TimeZoneUtils;
import au.com.royalpay.payment.tools.utils.XmlFormatUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Element;
import org.slf4j.Logger;
@ -42,12 +43,14 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@ -56,6 +59,11 @@ import java.net.URISyntaxException;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
/**
* Created by yixian on 2016-07-06.
*/

@ -0,0 +1,25 @@
package au.com.royalpay.payment.manage.mappers.client;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@AutoMapper(tablename = "cli_sub_merchant_id", pkName = "sub_merchant_id")
public interface ClientSubMerchantIdMapper {
@AutoSql(type = SqlType.SELECT)
List<JSONObject> listSubMerchantId(PageBounds pageBounds);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject subMerchantId);
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject subMerchantId);
@AutoSql(type = SqlType.DELETE)
void delete(@Param("sub_merchant_id") String sub_merchant_id);
}

@ -0,0 +1,19 @@
package au.com.royalpay.payment.manage.mappers.log;
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 = "log_client_sub_merchant_id", pkName = "id")
public interface LogClientSubMerchantIdMapper {
@AutoSql(type = SqlType.INSERT)
void save(JSONObject log);
@AutoSql(type = SqlType.SELECT)
List<JSONObject> listLogsByClientId(@Param("client_id") int client_id);
}

@ -0,0 +1,32 @@
package au.com.royalpay.payment.manage.mappers.payment;
import org.apache.ibatis.annotations.Param;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
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 java.util.List;
/**
* Create by yixian at 2017-12-05 23:13
*/
@AutoMapper(tablename = "pmt_sub_merchant_id", pkName = "sub_merchant_id")
public interface CommonSubMerchantIdMapper {
@AutoSql(type = SqlType.SELECT)
List<JSONObject> list(@Param("is_valid") boolean is_valid, @Param("sub_merchant_id") String sub_merchant_id,PageBounds pageBounds);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject record);
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject record);
@AutoSql(type = SqlType.SELECT)
JSONObject find(@Param("sub_merchant_id")String sub_merchant_id);
}

@ -0,0 +1,24 @@
package au.com.royalpay.payment.manage.mappers.risk;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
/**
* Create by yixian at 2017-12-21 11:45
*/
@AutoMapper(tablename = "risk_merchant_detail_log", pkName = "id")
public interface RiskMerchantDetailLogMapper {
@AutoSql(type = SqlType.INSERT)
void save(JSONObject record);
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject record);
PageList<JSONObject> query(JSONObject params, PageBounds pagination);
}

@ -0,0 +1,26 @@
package au.com.royalpay.payment.manage.mappers.risk;
import org.apache.ibatis.annotations.Param;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
/**
* Create by yixian at 2017-12-21 11:45
*/
@AutoMapper(tablename = "risk_merchant_record", pkName = "id")
public interface RiskMerchantRecordMapper {
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject record);
@AutoSql(type = SqlType.SELECT)
JSONObject findById(@Param("id") String id);
PageList<JSONObject> query(JSONObject params, PageBounds pagination);
}

@ -0,0 +1,27 @@
package au.com.royalpay.payment.manage.mappers.risk;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
/**
* Create by yixian at 2017-12-21 11:45
*/
@AutoMapper(tablename = "risk_transaction_log", pkName = "id")
public interface RiskTransactionLogMapper {
@AutoSql(type = SqlType.SELECT)
JSONObject findByOrderId(@Param("order_id") String order_id);
@AutoSql(type = SqlType.SELECT)
List<JSONObject> findByRecordId(@Param("record_id") String record_id);
PageList<JSONObject> query(JSONObject params, PageBounds pagination);
}

@ -0,0 +1,26 @@
package au.com.royalpay.payment.manage.mappers.risk;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
/**
* Create by yixian at 2017-12-21 11:45
*/
@AutoMapper(tablename = "risk_white_list", pkName = "client_id")
public interface RiskWhiteListMapper {
@AutoSql(type = SqlType.SELECT)
JSONObject findByClientMoniker(@Param("client_moniker") String client_moniker);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject record);
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject record);
}

@ -70,4 +70,8 @@ public interface ClientMapper {
List<String> listCityClientIds(@Param("city") String city, @Param("date") Date date);
List<String> listClientByCleanDays(@Param("clean_days") int clean_days);
List<JSONObject> listSubMerchantId();
List<JSONObject> listBySubMerchantId(@Param("sub_merchant_id") String sub_merchant_id);
}

@ -48,4 +48,7 @@ public interface ClientRateMapper {
JSONObject latestChannelCleanDays(@Param("rate_name")String rate_name, @Param("client_id")int client_id);
JSONObject latestExpiryConfig(@Param("client_id")int client_id,@Param("rate_name") String rate_name);
}

@ -0,0 +1,23 @@
package au.com.royalpay.payment.manage.merchantid.core;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
import java.util.Map;
/**
* Created by yuan on 2018/4/24.
*/
public interface MerchantIdManageService {
Map<String,List<JSONObject>> listSubMerchantId(JSONObject manager);
void generateClientsSunMerchantId();
JSONObject listNotTradeSubMerchantId(JSONObject manager);
List<JSONObject> showClientMoniker(JSONObject manager,String sub_merchant_id);
void save(JSONObject record);
void disable(String sub_merchant_id);
}

@ -0,0 +1,133 @@
package au.com.royalpay.payment.manage.merchantid.core.impl;
import au.com.royalpay.payment.channels.wechat.config.WeChatPayConfig;
import au.com.royalpay.payment.channels.wechat.runtime.MpPaymentApi;
import au.com.royalpay.payment.manage.analysis.mappers.ClientAnalysisMapper;
import au.com.royalpay.payment.manage.mappers.client.ClientSubMerchantIdMapper;
import au.com.royalpay.payment.manage.mappers.payment.CommonSubMerchantIdMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
import au.com.royalpay.payment.manage.merchantid.core.MerchantIdManageService;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.env.SysConfigManager;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Created by yuan on 2018/4/24.
*/
@Service
public class MerchantIdManageServiceImpl implements MerchantIdManageService {
@Autowired
private ClientMapper clientMapper;
@Autowired
private SysConfigManager sysConfigManager;
@Autowired
private ClientAnalysisMapper clientAnalysisMapper;
@Autowired
private ClientSubMerchantIdMapper clientSubMerchantIdMapper;
@Resource
private CommonSubMerchantIdMapper commonSubMerchantIdMapper;
@Resource
private MpPaymentApi mpPaymentApi;
@Override
public Map<String, List<JSONObject>> listSubMerchantId(JSONObject manager) {
List<JSONObject> clients = clientMapper.listSubMerchantId();
return getClientMap(clients);
}
@Override
public JSONObject listNotTradeSubMerchantId(JSONObject manager) {
List<JSONObject> clients = clientSubMerchantIdMapper.listSubMerchantId(new PageBounds(Order.formString("create_time.desc")));
Map<String, List<JSONObject>> merchantIdMap = clients.stream().filter(t->t.containsKey("merchant_id")).filter(t->t.containsKey("sub_merchant_id")).collect(Collectors.groupingBy(t->t.getString("merchant_id")));
JSONObject returnJason = new JSONObject();
returnJason.put("merchant_id_map",merchantIdMap);
returnJason.put("refresh_time",clients.size()>0?clients.get(0).getDate("create_time"):"");
return returnJason;
}
@Override
public void generateClientsSunMerchantId() {
String tempSubMerchantIds = sysConfigManager.getSysConfig().getString("temp_sub_mch_id");
List<JSONObject> clients = clientAnalysisMapper.notTradeSubMerchantId();
List<JSONObject> clientSubMerchantId = clientSubMerchantIdMapper.listSubMerchantId(new PageBounds(Order.formString("create_time.desc")));
Map<String, JSONObject> subMerchantIdMapFromDB = new HashMap<>();
for (JSONObject id : clientSubMerchantId) {
subMerchantIdMapFromDB.put(id.getString("sub_merchant_id"), id);
}
for (JSONObject client: clients) {
String subMerchantId = client.getString("sub_merchant_id");
if (subMerchantId != null && tempSubMerchantIds != null && tempSubMerchantIds.contains(subMerchantId)) {
client.put("temp_sub_merchant", true);
}
String id = client.getString("sub_merchant_id");
client.put("create_time",new Date());
if (subMerchantIdMapFromDB.containsKey(id)) {
subMerchantIdMapFromDB.remove(id);
clientSubMerchantIdMapper.update(client);
} else {
clientSubMerchantIdMapper.save(client);
}
}
for (String id : subMerchantIdMapFromDB.keySet()) {
clientSubMerchantIdMapper.delete(id);
}
}
@Override
public List<JSONObject> showClientMoniker(JSONObject manager,String sub_merchant_id) {
return clientMapper.listBySubMerchantId(sub_merchant_id);
}
@Override
public void save(JSONObject record) {
JSONObject sub_merchant_id = commonSubMerchantIdMapper.find(record.getString("sub_merchant_id"));
if(sub_merchant_id!=null){
throw new BadRequestException("当前商户号已经添加,请重新输入");
}
WeChatPayConfig.Merchant availableMerchant = mpPaymentApi.determineMerchant(record.getString("sub_merchant_id"));
if(availableMerchant == null){
throw new BadRequestException("未检索到对应的商户号,请验证子商户号是否正确");
}
record.put("merchant_id",availableMerchant.getMerchantId());
commonSubMerchantIdMapper.save(record);
}
@Override
public void disable(String sub_merchant_id) {
JSONObject record = new JSONObject();
record.put("sub_merchant_id",sub_merchant_id);
record.put("is_valid",false);
record.put("update_time",new Date());
commonSubMerchantIdMapper.update(record);
}
private Map<String, List<JSONObject>> getClientMap(List<JSONObject> clients){
String tempSubMerchantIds = sysConfigManager.getSysConfig().getString("temp_sub_mch_id");
for (JSONObject client: clients) {
String subMerchantId = client.getString("sub_merchant_id");
if (subMerchantId != null && tempSubMerchantIds != null && tempSubMerchantIds.contains(subMerchantId)) {
client.put("temp_sub_merchant", true);
}
}
Map<String, List<JSONObject>> clientsMap = clients.stream().filter(t->t.containsKey("merchant_id")).filter(t->t.containsKey("sub_merchant_id")).collect(Collectors.groupingBy(t->t.getString("merchant_id")));
return clientsMap;
}
}

@ -0,0 +1,75 @@
package au.com.royalpay.payment.manage.merchantid.web;
import au.com.royalpay.payment.manage.mappers.payment.CommonSubMerchantIdMapper;
import au.com.royalpay.payment.manage.merchantid.core.MerchantIdManageService;
import au.com.royalpay.payment.manage.permission.manager.RequireManager;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/sys/merchant_id")
public class MerchantIdManageController {
@Resource
private MerchantIdManageService merchantIdManageService;
@Resource
private CommonSubMerchantIdMapper commonSubMerchantIdMapper;
@RequestMapping(method = RequestMethod.GET)
@RequireManager(role = {ManagerRole.OPERATOR})
public Map<String,List<JSONObject>> listSubMerchantId(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return merchantIdManageService.listSubMerchantId(manager);
}
@RequestMapping(method = RequestMethod.GET,value = "/trade")
@RequireManager(role = {ManagerRole.OPERATOR})
public JSONObject listNotTradeSubMerchantId(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return merchantIdManageService.listNotTradeSubMerchantId(manager);
}
@RequestMapping(method = RequestMethod.POST,value = "/refresh")
@RequireManager(role = {ManagerRole.OPERATOR})
public void refreshClientsByTraded(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
merchantIdManageService.generateClientsSunMerchantId();
}
@RequestMapping(method = RequestMethod.GET,value = "/{sub_merchant_id}")
@RequireManager(role = {ManagerRole.OPERATOR})
public List<JSONObject> showClientMoniker(@PathVariable() String sub_merchant_id,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return merchantIdManageService.showClientMoniker(manager,sub_merchant_id);
}
@RequestMapping(value = "/common_sub_merchant_id", method = RequestMethod.GET)
@RequireManager(role = {ManagerRole.OPERATOR})
public List<JSONObject> listCommonSubMerchantId(@RequestParam(required = false) String sub_merchant_id, @RequestParam(defaultValue = "true") boolean is_valid) {
return commonSubMerchantIdMapper.list(is_valid,sub_merchant_id,new PageBounds(Order.formString("create_time.desc")));
}
@RequestMapping(value = "/common_sub_merchant_id/{sub_merchant_id}", method = RequestMethod.POST)
@RequireManager(role = {ManagerRole.OPERATOR})
public void addCommonSubMerchantId(@PathVariable String sub_merchant_id,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
JSONObject record = new JSONObject();
record.put("sub_merchant_id",sub_merchant_id);
record.put("operator",manager.getString("display_name"));
record.put("create_time",new Date());
merchantIdManageService.save(record);
}
@RequestMapping(value = "/common_sub_merchant_id/{sub_merchant_id}", method = RequestMethod.PUT)
@RequireManager(role = {ManagerRole.OPERATOR})
public void disableCommonSubMerchantId(@PathVariable String sub_merchant_id) {
merchantIdManageService.disable(sub_merchant_id);
}
}

@ -35,6 +35,8 @@ public class ClientRegisterInfo {
private String alipayIndustry;
@JSONField(name = "company_photo")
private String companyPhoto;
@JSONField(name = "store_photo")
private String storePhoto;
@JSONField(name = "company_website")
private String companyWebsite;
@JSONField(name = "company_phone")
@ -67,6 +69,11 @@ public class ClientRegisterInfo {
private String client_apply_id;
private String business_hours;
private String merchant_introduction;
private String merchant_tag;
private String merchant_video_url;
public JSONObject insertObject() {
JSONObject res = (JSONObject) JSON.toJSON(this);
if (client_apply_id==null){
@ -145,6 +152,14 @@ public class ClientRegisterInfo {
this.companyPhoto = companyPhoto;
}
public String getStorePhoto() {
return storePhoto;
}
public void setStorePhoto(String storePhoto) {
this.storePhoto = storePhoto;
}
public String getCompanyWebsite() {
return companyWebsite;
}
@ -320,4 +335,36 @@ public class ClientRegisterInfo {
public void setRoyalpayindustry(String royalpayindustry) {
this.royalpayindustry = royalpayindustry;
}
public String getBusiness_hours() {
return business_hours;
}
public void setBusiness_hours(String business_hours) {
this.business_hours = business_hours;
}
public String getMerchant_introduction() {
return merchant_introduction;
}
public void setMerchant_introduction(String merchant_introduction) {
this.merchant_introduction = merchant_introduction;
}
public String getMerchant_tag() {
return merchant_tag;
}
public void setMerchant_tag(String merchant_tag) {
this.merchant_tag = merchant_tag;
}
public String getMerchant_video_url() {
return merchant_video_url;
}
public void setMerchant_video_url(String merchant_video_url) {
this.merchant_video_url = merchant_video_url;
}
}

@ -286,4 +286,6 @@ public interface ClientManager {
void clearCacheSubMerchantIdApplices(String clientMoniker);
JSONObject getCheckClientInfo(int client_id,String account_id, String channel);
List<JSONObject> getClientSubMerchantIdLogs(String clientMoniker,JSONObject manager);
}

@ -14,6 +14,7 @@ import au.com.royalpay.payment.manage.appclient.beans.AppClientBean;
import au.com.royalpay.payment.manage.device.core.DeviceManager;
import au.com.royalpay.payment.manage.mappers.financial.FinancialBDConfigMapper;
import au.com.royalpay.payment.manage.mappers.log.ClientsOperationLogMapper;
import au.com.royalpay.payment.manage.mappers.log.LogClientSubMerchantIdMapper;
import au.com.royalpay.payment.manage.mappers.log.LogSettleMailMapper;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.redpack.ActClientInvitationCodeMapper;
@ -254,6 +255,9 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
private MessageSource messageSource;
@Resource
private ClientsOperationLogMapper clientsOperationLogMapper;
@Resource
private LogClientSubMerchantIdMapper logClientSubMerchantIdMapper;
@Resource
private ClientInfoCacheSupport clientInfoCacheSupport;
@Resource
@ -310,6 +314,10 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
client.put("show_all_permission", true);
int role = manager != null ? manager.getIntValue("role") : 0;
if (manager != null) {
if(ManagerRole.OPERATOR.hasRole(role)){
List<JSONObject> log = logClientSubMerchantIdMapper.listLogsByClientId(client.getInteger("client_id"));
client.put("sub_merchant_id_log", log.size()>0?true:false);
}
if (ManagerRole.BD_USER.hasRole(role)) {
int checkBDPermission = clientBDMapper.checkBDPermission(client.getIntValue("client_id"), manager.getString("manager_id"));
client.put("show_all_permission", checkBDPermission > 0);
@ -610,18 +618,39 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
JSONObject update = new JSONObject();
int clientId = client.getIntValue("client_id");
String originSubMerchantId = client.getString("sub_merchant_id");
update.put("client_id", clientId);
String subMerchantId = subMerchantInfo.getString("sub_merchant_id");
WeChatPayConfig.Merchant availableMerchant = mpPaymentApi.determineMerchant(subMerchantId);
clientModifySupport.processClientModify(
new MerchantIdModify(manager, clientMoniker, subMerchantId, availableMerchant == null ? null : availableMerchant.getMerchantId()));
update.put("merchant_id", availableMerchant == null ? null : availableMerchant.getMerchantId());
update.put("sub_merchant_id", subMerchantId);
try{
recordSubMerchantLog(client,subMerchantInfo,manager);
}catch(Exception e){
logger.error("记录log_client_sub_merchant_id失败",e);
}
clientMapper.update(update);
List<JSONObject> children = clientMapper.listChildClients(clientId);
for (JSONObject child : children) {
if (Objects.equals(child.getString("sub_merchant_id"), originSubMerchantId)) {
update.put("client_id", child.getIntValue("client_id"));
clientModifySupport.processClientModify(
new MerchantIdModify(manager, clientMoniker, subMerchantId, availableMerchant == null ? null : availableMerchant.getMerchantId()));
try{
recordSubMerchantLog(child,subMerchantInfo,manager);
}catch(Exception e){
logger.error("记录log_client_sub_merchant_id失败",e);
}
clientMapper.update(update);
}
}
clientInfoCacheSupport.clearClientCache(clientId);
}
private void recordSubMerchantLog(JSONObject client,JSONObject subMerchantInfo,JSONObject manager){
JSONObject log = new JSONObject();
log.put("sub_merchant_id_after",subMerchantInfo.getString("sub_merchant_id"));
log.put("operator",manager.getString("display_name"));
log.put("create_time",new Date());
log.put("client_id",client.getIntValue("client_id"));
log.put("sub_merchant_id_before",client.getString("sub_merchant_id"));
logClientSubMerchantIdMapper.save(log);
}
@Override
@ -3280,4 +3309,14 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}
return sourceStr;
}
@Override
public List<JSONObject> getClientSubMerchantIdLogs(String clientMoniker, JSONObject manager) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkOrgPermission(manager, client);
return logClientSubMerchantIdMapper.listLogsByClientId(client.getInteger("client_id"));
}
}

@ -230,6 +230,11 @@ public class PartnerManageController {
clientManager.refusePartner(clientMoniker, manager, refuse.getString("refuse_remark"));
}
@ManagerMapping(value = "/{clientMoniker}/common_sub_merchant_id", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR})
public void switchCommonSubMerchantId(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.switchPermission(manager, clientMoniker, "common_sub_merchant_id", 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"));
@ -523,4 +528,9 @@ public class PartnerManageController {
return clientManager.listMerchantIds(clientMoniker,manager);
}
@ManagerMapping(value = "/{clientMoniker}/get_sub_merchant_id_logs",method = RequestMethod.GET,role = {ManagerRole.OPERATOR})
public List<JSONObject> getClientSubMerchantIdLogs(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.getClientSubMerchantIdLogs(clientMoniker,manager);
}
}

@ -0,0 +1,69 @@
package au.com.royalpay.payment.manage.risk.bean;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
public class AddRiskDetailLog {
@JsonProperty("record_id")
private String record_id;
@JsonProperty("files")
private String files;
@JsonProperty("operation")
private String operation;
@JsonProperty("remark")
private String remark;
public JSONObject params() {
JSONObject params = new JSONObject();
params.put("record_id", this.record_id);
if (StringUtils.isNotEmpty(this.files)) {
params.put("files", this.files);
}
if (StringUtils.isNotEmpty(this.operation)) {
params.put("operation", this.operation);
}
if (StringUtils.isNotEmpty(this.remark)) {
params.put("remark", this.remark);
}
return params;
}
public String getRecord_id() {
return record_id;
}
public void setRecord_id(String record_id) {
this.record_id = record_id;
}
public String getFiles() {
return files;
}
public void setFiles(String files) {
this.files = files;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

@ -0,0 +1,37 @@
package au.com.royalpay.payment.manage.risk.bean;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
public class DealRiskRecord {
private String recordId;
private BigDecimal limitAmount;
@JsonProperty(defaultValue = "false")
private boolean disableMerchat;
public String getRecordId() {
return recordId;
}
public void setRecordId(String recordId) {
this.recordId = recordId;
}
public BigDecimal getLimitAmount() {
return limitAmount;
}
public void setLimitAmount(BigDecimal limitAmount) {
this.limitAmount = limitAmount;
}
public Boolean getDisableMerchat() {
return disableMerchat;
}
public void setDisableMerchat(Boolean disableMerchat) {
this.disableMerchat = disableMerchat;
}
}

@ -0,0 +1,70 @@
package au.com.royalpay.payment.manage.risk.bean;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException;
public class QueryRiskDetail {
private String record_id;
private String c_end_time;
private int client_id;
private int limit = 20;
private int page;
public JSONObject toParams() {
JSONObject params = new JSONObject();
params.put("record_id", this.record_id);
params.put("client_id", this.client_id);
try {
if (c_end_time != null) {
params.put("c_end_time", DateUtils.parseDate(this.c_end_time, new String[] { "yyyy-MM-dd HH:mm:ss" }));
}
} catch (ParseException e) {
}
return params;
}
public String getRecord_id() {
return record_id;
}
public void setRecord_id(String record_id) {
this.record_id = record_id;
}
public String getC_end_time() {
return c_end_time;
}
public void setC_end_time(String c_end_time) {
this.c_end_time = c_end_time;
}
public int getClient_id() {
return client_id;
}
public void setClient_id(int client_id) {
this.client_id = client_id;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
}

@ -0,0 +1,69 @@
package au.com.royalpay.payment.manage.risk.bean;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException;
public class QueryRiskOrder {
private String record_id;
private String c_end_time;
private int client_id;
private int limit = 20;
private int page;
public JSONObject toParams() {
JSONObject params = new JSONObject();
params.put("record_id", this.record_id);
params.put("client_id", this.client_id);
try {
if (c_end_time != null) {
params.put("c_end_time", DateUtils.parseDate(this.c_end_time, new String[] { "yyyy-MM-dd HH:mm:ss" }));
}
} catch (ParseException e) {
}
return params;
}
public String getRecord_id() {
return record_id;
}
public void setRecord_id(String record_id) {
this.record_id = record_id;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public String getC_end_time() {
return c_end_time;
}
public void setC_end_time(String c_end_time) {
this.c_end_time = c_end_time;
}
public int getClient_id() {
return client_id;
}
public void setClient_id(int client_id) {
this.client_id = client_id;
}
}

@ -0,0 +1,91 @@
package au.com.royalpay.payment.manage.risk.bean;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException;
public class QueryRiskRecord {
private String status;
private String client_moniker;
private String record_id;
private String c_end_time;
private int client_id;
private int limit = 20;
private int page;
public JSONObject toParams() {
JSONObject params = new JSONObject();
params.put("status", this.status);
params.put("client_moniker", this.client_moniker);
params.put("record_id", this.record_id);
params.put("client_id", this.client_id);
try {
if (c_end_time != null) {
params.put("c_end_time", DateUtils.parseDate(this.c_end_time, new String[] { "yyyy-MM-dd HH:mm:ss" }));
}
} catch (ParseException e) {
}
return params;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getRecord_id() {
return record_id;
}
public void setRecord_id(String record_id) {
this.record_id = record_id;
}
public String getClient_moniker() {
return client_moniker;
}
public void setClient_moniker(String client_moniker) {
this.client_moniker = client_moniker;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public String getC_end_time() {
return c_end_time;
}
public void setC_end_time(String c_end_time) {
this.c_end_time = c_end_time;
}
public int getClient_id() {
return client_id;
}
public void setClient_id(int client_id) {
this.client_id = client_id;
}
}

@ -0,0 +1,37 @@
package au.com.royalpay.payment.manage.risk.core;
import au.com.royalpay.payment.manage.risk.bean.AddRiskDetailLog;
import au.com.royalpay.payment.manage.risk.bean.DealRiskRecord;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskDetail;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskOrder;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskRecord;
import com.alibaba.fastjson.JSONObject;
public interface RiskMerchantService {
void addDetailLog(AddRiskDetailLog addRiskDetailLog, JSONObject account);
void DropOrderRiskRecord(JSONObject account,String recordId);
void noopRiskRecord(JSONObject account,String recordId);
void dealRiskRecord(JSONObject account,DealRiskRecord dealRiskRecord);
void dealRiskRecordDirectly(JSONObject account,String record_id);
JSONObject getRiskOrders(QueryRiskOrder queryRiskOrder);
JSONObject getRiskRecords(QueryRiskRecord queryRiskRecord);
void addWhiteList(String client_moinker);
void disableWhiteList(String client_moinker);
JSONObject getRecordById(String record_id);
JSONObject getRiskDetails(QueryRiskDetail queryRiskDetail);
}

@ -0,0 +1,216 @@
package au.com.royalpay.payment.manage.risk.core.impl;
import au.com.royalpay.payment.manage.mappers.risk.RiskMerchantDetailLogMapper;
import au.com.royalpay.payment.manage.mappers.risk.RiskMerchantRecordMapper;
import au.com.royalpay.payment.manage.mappers.risk.RiskTransactionLogMapper;
import au.com.royalpay.payment.manage.mappers.risk.RiskWhiteListMapper;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.risk.bean.AddRiskDetailLog;
import au.com.royalpay.payment.manage.risk.bean.DealRiskRecord;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskDetail;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskOrder;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskRecord;
import au.com.royalpay.payment.manage.risk.core.RiskMerchantService;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.NotFoundException;
import au.com.royalpay.payment.tools.utils.PageListUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import javax.annotation.Resource;
@Service
public class RiskMerchantServiceImpl implements RiskMerchantService {
@Resource
private RiskMerchantRecordMapper riskMerchantRecordMapper;
@Resource
private RiskMerchantDetailLogMapper riskMerchantDetailLogMapper;
@Resource
private RiskTransactionLogMapper riskTransactionLogMapper;
@Resource
private RiskWhiteListMapper riskWhiteListMapper;
@Resource
private ClientManager clientManager;
@Override
@Transactional
public void addDetailLog(AddRiskDetailLog addRiskDetailLog, JSONObject account) {
JSONObject record = riskMerchantRecordMapper.findById(addRiskDetailLog.getRecord_id());
if (record == null) {
throw new NotFoundException("Risk Record Not Found Please Check");
}
JSONObject detail = addRiskDetailLog.params();
detail.put("auditor", account.getString("display_name"));
detail.put("client_id", record.getIntValue("client_id"));
detail.put("auditor_id", account.getString("manager_id"));
detail.put("create_time", new Date());
riskMerchantDetailLogMapper.save(detail);
record.put("status",2);
riskMerchantRecordMapper.update(record);
}
@Override
@Transactional
public void DropOrderRiskRecord(JSONObject account, String recordId) {
JSONObject riskRecord = riskMerchantRecordMapper.findById(recordId);
if (riskRecord == null) {
throw new NotFoundException("Risk Record Not Found");
}
if (riskRecord.getIntValue("status") != 0) {
throw new BadRequestException("The Record Has Been Handled");
}
JSONObject record = new JSONObject();
record.put("id", recordId);
record.put("status", "1");
riskMerchantRecordMapper.update(record);
JSONObject detail = new JSONObject();
detail.put("record_id", recordId);
detail.put("client_id", riskRecord.getIntValue("client_id"));
detail.put("auditor", account.getString("display_name"));
detail.put("auditor_id", account.getString("manager_id"));
detail.put("remark", "进行掉单处理");
detail.put("create_time", new Date());
riskMerchantDetailLogMapper.save(detail);
}
@Override
@Transactional
public void noopRiskRecord(JSONObject account, String recordId) {
JSONObject riskRecord = riskMerchantRecordMapper.findById(recordId);
if (riskRecord == null) {
throw new NotFoundException("Risk Record Not Found");
}
if (riskRecord.getIntValue("status") != 0) {
throw new BadRequestException("The Record Has Been Handled");
}
JSONObject record = new JSONObject();
record.put("id", recordId);
record.put("status", "2");
riskMerchantRecordMapper.update(record);
JSONObject detail = new JSONObject();
detail.put("record_id", recordId);
detail.put("client_id", riskRecord.getIntValue("client_id"));
detail.put("auditor", account.getString("display_name"));
detail.put("remark", "不做处理");
detail.put("create_time", new Date());
riskMerchantDetailLogMapper.save(detail);
}
@Override
@Transactional
public void dealRiskRecord(JSONObject account, DealRiskRecord dealRiskRecord) {
JSONObject record = riskMerchantRecordMapper.findById(dealRiskRecord.getRecordId());
if (record == null) {
throw new NotFoundException("Risk Record Not Found Please Check");
}
if (record.getIntValue("status") != 0) {
throw new BadRequestException("The Record Has Been Handled");
}
String remark = "";
if (dealRiskRecord.getLimitAmount() != null) {
clientManager.setMaxOrderAmount(record.getString("client_moniker"), dealRiskRecord.getLimitAmount());
remark = remark + "限额" + dealRiskRecord.getLimitAmount();
}
if (dealRiskRecord.getDisableMerchat()) {
clientManager.switchChannelPermission(account, record.getString("client_moniker"), "Wechat", false);
clientManager.switchChannelPermission(account, record.getString("client_moniker"), "Alipay", false);
remark = remark + " 关闭支付通道";
}
JSONObject detail = new JSONObject();
detail.put("record_id", dealRiskRecord.getRecordId());
detail.put("client_id", record.getIntValue("client_id"));
detail.put("auditor", account.getString("display_name"));
detail.put("remark", StringUtils.isEmpty(remark) ? null : (remark = "处理结果:" + remark));
detail.put("create_time", new Date());
riskMerchantDetailLogMapper.save(detail);
record.put("status", 2);
riskMerchantRecordMapper.update(record);
}
@Override
@Transactional
public void dealRiskRecordDirectly(JSONObject account, String record_id) {
JSONObject record = riskMerchantRecordMapper.findById(record_id);
if (record == null) {
throw new NotFoundException("Risk Record Not Found Please Check");
}
if (record.getIntValue("status") != 0) {
throw new BadRequestException("The Record Has Been Handled");
}
JSONObject detail = new JSONObject();
detail.put("record_id", record_id);
detail.put("client_id", record.getIntValue("client_id"));
detail.put("auditor", account.getString("display_name"));
detail.put("auditor_id", account.getString("manager_id"));
detail.put("remark", "结停");
detail.put("create_time", new Date());
riskMerchantDetailLogMapper.save(detail);
JSONObject recordUpdate = new JSONObject();
recordUpdate.put("id",record_id);
recordUpdate.put("status", 1);
riskMerchantRecordMapper.update(recordUpdate);
}
@Override
public JSONObject getRiskOrders(QueryRiskOrder queryRiskOrder) {
return PageListUtils.buildPageListResult(
riskTransactionLogMapper.query(queryRiskOrder.toParams(), new PageBounds(queryRiskOrder.getPage(), queryRiskOrder.getLimit())));
}
@Override
public JSONObject getRiskRecords(QueryRiskRecord queryRiskRecord) {
return PageListUtils.buildPageListResult(
riskMerchantRecordMapper.query(queryRiskRecord.toParams(), new PageBounds(queryRiskRecord.getPage(), queryRiskRecord.getLimit())));
}
@Override
public void addWhiteList(String client_moinker) {
JSONObject white = riskWhiteListMapper.findByClientMoniker(client_moinker);
if (white != null) {
white.put("is_valid", true);
riskWhiteListMapper.update(white);
return;
}
JSONObject client = clientManager.getClientInfoByMoniker(client_moinker);
if (client == null) {
throw new NotFoundException("Merchant Not Found Please Check");
}
JSONObject record = new JSONObject();
record.put("client_id", client.getIntValue("client_id"));
record.put("client_moniker", client.getString("client_moinker"));
record.put("create_time", new Date());
riskWhiteListMapper.save(record);
}
@Override
public void disableWhiteList(String client_moinker) {
JSONObject white = riskWhiteListMapper.findByClientMoniker(client_moinker);
if (white == null) {
throw new NotFoundException("White List Not Found Please Check");
}
white.put("is_valid", false);
riskWhiteListMapper.update(white);
}
@Override
public JSONObject getRecordById(String record_id) {
return riskMerchantRecordMapper.findById(record_id);
}
@Override
public JSONObject getRiskDetails(QueryRiskDetail queryRiskDetail) {
return PageListUtils.buildPageListResult(
riskMerchantDetailLogMapper.query(queryRiskDetail.toParams(), new PageBounds(queryRiskDetail.getPage(), queryRiskDetail.getLimit())));
}
}

@ -0,0 +1,94 @@
package au.com.royalpay.payment.manage.risk.web;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.risk.bean.AddRiskDetailLog;
import au.com.royalpay.payment.manage.risk.bean.DealRiskRecord;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskDetail;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskOrder;
import au.com.royalpay.payment.manage.risk.bean.QueryRiskRecord;
import au.com.royalpay.payment.manage.risk.core.RiskMerchantService;
import au.com.royalpay.payment.tools.CommonConsts;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* Created by wangning on 08/12/2016.
*/
@RestController
@ManagerMapping(value = "/sys/risk")
public class RiskController {
@Resource
private RiskMerchantService riskMerchantService;
@RequestMapping(value = "/records", method = RequestMethod.GET)
public JSONObject list(QueryRiskRecord recordQuery) {
return riskMerchantService.getRiskRecords(recordQuery);
}
@RequestMapping(value = "/records/{record_id}", method = RequestMethod.GET)
public JSONObject getById(@PathVariable String record_id) {
return riskMerchantService.getRecordById(record_id);
}
@RequestMapping(value = "/records/{record_id}/dropOrder", method = RequestMethod.PUT)
public void dropOrder(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String record_id) {
riskMerchantService.DropOrderRiskRecord(manager, record_id);
}
@RequestMapping(value = "/records/{record_id}/noop", method = RequestMethod.PUT)
public void noop(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String record_id) {
riskMerchantService.noopRiskRecord(manager, record_id);
}
@RequestMapping(value = "/records/{record_id}/directly", method = RequestMethod.PUT)
public void directly(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String record_id) {
riskMerchantService.dealRiskRecordDirectly(manager, record_id);
}
@RequestMapping(value = "/records/{record_id}/deal",method = RequestMethod.PUT)
public void dealRecord(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String record_id, @RequestBody DealRiskRecord dealRiskRecord){
dealRiskRecord.setRecordId(record_id);
riskMerchantService.dealRiskRecord(manager,dealRiskRecord);
}
@RequestMapping(value = "/orders", method = RequestMethod.GET)
public JSONObject getRiskOrders(QueryRiskOrder queryRiskOrder) {
return riskMerchantService.getRiskOrders(queryRiskOrder);
}
@RequestMapping(value = "/white/{client_moniker}", method = RequestMethod.POST)
public void addWhiteList(@PathVariable String client_moniker) {
riskMerchantService.addWhiteList(client_moniker);
}
@RequestMapping(value = "/white/{client_moniker}/disable", method = RequestMethod.PUT)
public void disableWhiteList(@PathVariable String client_moniker) {
riskMerchantService.disableWhiteList(client_moniker);
}
@RequestMapping(value = "/records/uploadFiles", method = RequestMethod.POST)
public void addRecordLog(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@RequestBody AddRiskDetailLog addRiskDetailLog) {
// riskMerchantService.addDetailLog(addRiskDetailLog,manager);
}
@RequestMapping(value = "/details", method = RequestMethod.GET)
public JSONObject listDetails(QueryRiskDetail queryRiskDetail) {
return riskMerchantService.getRiskDetails(queryRiskDetail);
}
@RequestMapping(value = "/details/remark", method = RequestMethod.POST)
public void addDetailRemark(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@RequestBody AddRiskDetailLog addRiskDetailLog ) {
riskMerchantService.addDetailLog(addRiskDetailLog,manager);
}
}

@ -15,6 +15,7 @@ import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@ -29,7 +30,7 @@ import javax.annotation.Resource;
* Created by wangning on 2018/1/2.
*/
@Component
//@ConditionalOnProperty(value = "app.run-tasks", havingValue = "true")
@ConditionalOnProperty(value = "app.run-tasks", havingValue = "true")
public class PostponeClientTask {
Logger logger = LoggerFactory.getLogger(PostponeClientTask.class);
@ -44,7 +45,7 @@ public class PostponeClientTask {
@Resource
private ManagerMapper managerMapper;
// @Scheduled(cron = "0 30 8 * * ?")
@Scheduled(cron = "0 30 8 * * ?")
public void checkGreenChannel() {
Date now = new Date();
Date tomorrow = DateUtils.addDays(now, 1);
@ -60,8 +61,9 @@ public class PostponeClientTask {
expiryClients.put(p.getInteger("client_id"), p);
});
expiryClients.values().forEach(p -> {
List<JSONObject> adminAccounts = clientAccountMapper.listAdminAccounts(p.getIntValue("client_id"));
List<JSONObject> clientRates = clientRateMapper.maxChannelExpiryTime(p.getIntValue("client_id"), null);
int client_id = p.getIntValue("client_id");
List<JSONObject> adminAccounts = clientAccountMapper.listAdminAccounts(client_id);
List<JSONObject> clientRates = clientRateMapper.maxChannelExpiryTime(client_id, null);
JSONObject wechatRate = clientRateMapper.latestChannelCleanDays("Wechat", p.getIntValue("client_id"));
int cleanDays = 1;
if (wechatRate.getInteger("clean_days") != null) {
@ -71,16 +73,17 @@ public class PostponeClientTask {
}
int finalCleanDays = cleanDays;
clientRates.forEach(o -> {
o.remove("client_rate_id");
o.put("active_time", tomorrow);
o.put("manager_id", 0);
o.put("expiry_time", yearTomorrow);
o.put("create_time", now);
o.put("update_time", now);
o.put("clean_days", finalCleanDays);
o.put("manager_name", "System");
o.put("remark", "费率到期系统自动延期1年");
clientRateMapper.saveRate(o);
JSONObject record = clientRateMapper.latestExpiryConfig(client_id,o.getString("rate_name"));
record.remove("client_rate_id");
record.put("active_time", now);
record.put("manager_id", 0);
record.put("expiry_time", yearTomorrow);
record.put("create_time", now);
record.put("update_time", now);
record.put("clean_days", finalCleanDays);
record.put("manager_name", "System");
record.put("remark", "费率到期系统自动延期1年");
clientRateMapper.saveRate(record);
});
adminAccounts.forEach(o -> {

@ -0,0 +1,19 @@
package au.com.royalpay.payment.manage.task;
import au.com.royalpay.payment.manage.merchantid.core.MerchantIdManageService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@ConditionalOnProperty(value = "app.run-tasks", havingValue = "true")
public class SubMerchantIdTaskManager {
@Resource
private MerchantIdManageService merchantIdManageService;
@Scheduled(cron = "0 0 4 * * ?")
public void analysisDashboard(){
merchantIdManageService.generateClientsSunMerchantId();
}
}

@ -134,4 +134,18 @@
GROUP BY c.royalpayindustry order by partner_counts desc
</select>
<select id="notTradeSubMerchantId" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT COUNT(DISTINCT c.client_id) client_count,
c.sub_merchant_id,
c.merchant_id
FROM sys_clients c
WHERE c.sub_merchant_id not in
(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
AND (c.approve_result = 1 OR c.approve_result= 2) AND c.is_valid = 1
]]>
GROUP by c.sub_merchant_id
</select>
</mapper>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="au.com.royalpay.payment.manage.mappers.payment.CommonSubMerchantIdMapper">
<select id="list" resultType="com.alibaba.fastjson.JSONObject">
select * from pmt_sub_merchant_id
where is_valid = #{is_valid}
<if test="sub_merchant_id!=null">
and sub_merchant_id = #{sub_merchant_id}
</if>
</select>
</mapper>

@ -658,7 +658,8 @@
t.transaction_id,
t.exchange_rate,
t.clearing_status,
t.settle_amount
t.settle_amount,
t.clearing_status = 2 pre_auth
from pmt_orders o
left join pmt_transactions t on t.order_id=o.order_id and t.channel!='Settlement' and t.system_generate=0
<where>
@ -687,6 +688,7 @@
<foreach collection="channel" item="chan" open="(" close=")" separator=" or ">o.channel=#{chan}
</foreach>
</if>
<if test="clearing_status!=null">and t.clearing_status=#{clearing_status}</if>
</where>
</select>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="au.com.royalpay.payment.manage.mappers.risk.RiskMerchantDetailLogMapper">
<select id="query" resultType="com.alibaba.fastjson.JSONObject">
select *
from risk_merchant_detail_log
<where>
<if test="record_id!=null">
and record_id = #{record_id}
</if>
<if test="client_id!=0">
and client_id = #{client_id}
</if>
</where>
order by create_time desc
</select>
</mapper>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="au.com.royalpay.payment.manage.mappers.risk.RiskMerchantRecordMapper">
<select id="query" resultType="com.alibaba.fastjson.JSONObject">
SELECT *
FROM risk_merchant_record
<where>
<if test="record_id!=null">
and id = #{record_id}
</if>
<if test="status != null">
and status = #{status}
</if>
<if test="client_moniker!=null">
and client_moniker = #{client_moniker}
</if>
<if test="c_end_time!=null">
and create_time &lt; #{c_end_time}
</if>
<if test="client_id != 0">
and client_id = #{client_id}
</if>
</where>
order by create_time desc
</select>
</mapper>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="au.com.royalpay.payment.manage.mappers.risk.RiskTransactionLogMapper">
<select id="query" resultType="com.alibaba.fastjson.JSONObject">
SELECT *
FROM risk_transaction_log
<where>
<if test="record_id!=null">
and record_id = #{record_id}
</if>
<if test="client_id !=0">
and client_id = #{client_id}
</if>
<if test="c_end_time != null">
and create_time &lt; #{c_end_time}
</if>
</where>
order by create_time desc
</select>
</mapper>

@ -289,4 +289,25 @@
inner join sys_client_config cc
WHERE c.is_valid = 1 and cc.clean_days = #{clean_days}
</select>
<select id="listSubMerchantId" resultType="com.alibaba.fastjson.JSONObject">
SELECT
COUNT(DISTINCT c.client_id) client_count,
c.sub_merchant_id,
c.merchant_id
FROM sys_clients c
WHERE (c.approve_result = 1 OR c.approve_result= 2) AND c.is_valid = 1 AND c.sub_merchant_id IS NOT NULL
AND c.merchant_id IS NOT NULL
GROUP BY c.sub_merchant_id
</select>
<select id="listBySubMerchantId" resultType="com.alibaba.fastjson.JSONObject">
SELECT
c.client_moniker,
c.sub_merchant_id,
c.merchant_id
FROM sys_clients c
WHERE (c.approve_result = 1 OR c.approve_result= 2) AND c.is_valid = 1 AND c.sub_merchant_id IS NOT NULL
AND c.merchant_id IS NOT NULL AND c.sub_merchant_id = #{sub_merchant_id}
</select>
</mapper>

@ -139,4 +139,12 @@
order by cr.expiry_time desc
limit 1
</select>
<select id="latestExpiryConfig" resultType="com.alibaba.fastjson.JSONObject">
SELECT * FROM
sys_client_rates
WHERE client_id = #{client_id} and rate_name =#{rate_name}
order by expiry_time desc
limit 1
</select>
</mapper>

@ -13,7 +13,7 @@
left join sys_accounts a on a.account_id = cc.sign_account_id
<where>
<if test="client_moniker!=null">
cc.create_time = #{client_moniker}
c.client_moniker = #{client_moniker}
</if>
</where>
order by create_time desc

@ -234,6 +234,7 @@ margin-bottom: 10%;"/>
<i class="fa fa-sitemap"></i> <span>商户管理|Partner Manage</span>
</a>
</li>
<li ui-sref-active="active"
ng-if="('partnerapply'|withModule) && (currentUser.org_id==null||currentUser.org_id==1)">
<a ui-sref="partner_application" ui-sref-opts="{reload:true}">
@ -393,6 +394,11 @@ margin-bottom: 10%;"/>
<li class="header nav-header" ng-if="'0100001'|withRole">基础设置|Basic Settings</li>
<li ui-sref-active="active" ng-if="('10'|withRole)&&('merchantIdManage'|withModule)">
<a ui-sref="merchant_id_manage" ui-sref-opts="{reload:true}">
<i class="fa fa-sitemap"></i> <span>商户号管理</span>
</a>
</li>
<li ui-sref-active="active" ng-if="'org'|withModule">
<a ui-sref="organizations" ui-sref-opts="{reload:true}">
<i class="fa fa-users"></i> <span>组织管理|Organizations</span>

@ -19,6 +19,10 @@
<li ui-sref-active-eq="active" ng-if="('monitor'|withModule)&&(currentUser.org_id==null)">
<a ui-sref="analysis_monitoring.pre_refund"><i class="fa fa-tv"></i> <span>欠款|Pre Refund</span></a>
</li>
<li ui-sref-active-eq="active">
<a ui-sref="analysis_monitoring.risk_manager"><i class="fa fa-tv"></i> <span>风控记录|Risk Records</span></a>
</li>
</ul>
</div>
</div>

@ -243,7 +243,6 @@
<th>Currency</th>
<th>Input Amount</th>
<th>Total Amount</th>
<th>Clearing Amount</th>
<th>Surcharge Rate</th>
<th>Surcharge Amount</th>
<th>Settle Amount</th>
@ -260,7 +259,6 @@
<td ng-bind="tr.transaction_currency"></td>
<td ng-bind="tr.display_amount|currency:''"></td>
<td ng-bind="tr.transaction_amount|currency:''"></td>
<td ng-bind="tr.clearing_amount|currency:''"></td>
<td ng-bind="tr.surcharge_rate|percentage:1"></td>
<td ng-bind="(tr.total_surcharge?tr.total_surcharge:0)|currency:''"></td>
<td ng-bind="tr.settle_amount|currency:''"></td>
@ -281,7 +279,6 @@
<th>Transaction Time</th>
<th>Currency</th>
<th>Total Amount</th>
<th>Clearing Amount</th>
<th>Surcharge Rate</th>
<th>Surcharge Amount</th>
<th>Settle Amount</th>
@ -297,7 +294,6 @@
<td ng-bind="tr.transaction_time"></td>
<td ng-bind="tr.transaction_currency"></td>
<td ng-bind="tr.transaction_amount|currency:''"></td>
<td ng-bind="tr.clearing_amount|currency:''"></td>
<td ng-bind="tr.surcharge_rate|percentage:1"></td>
<td ng-bind="(tr.total_surcharge?tr.total_surcharge:0)|currency:''"></td>
<td ng-bind="tr.settle_amount|currency:''"></td>

@ -36,8 +36,13 @@ define(['../app'], function (app) {
}
}
}]);
app.controller('orderDetailDialogCtrl', ['$scope', 'order', function ($scope, order) {
app.controller('orderDetailDialogCtrl', ['$scope', 'order','$http', function ($scope, order,$http) {
$scope.order = order.data;
$scope.getPayLocation=function (ip) {
$http.get('/dev/ip/'+ip).then(function (res) {
$scope.pay_location = res.data;
})
}
}]);
app.controller('orderDetailEditCtrl', ['$scope', '$http', 'commonDialog', 'order', function ($scope, $http, commonDialog,order) {
$scope.order = order.data;

@ -75,7 +75,9 @@
<div class="form-group" ng-if="order.customer_ip">
<label class="control-label col-xs-3">IP</label>
<div class="col-xs-9">
<p class="form-control-static" ng-bind="order.customer_ip"></p>
<p class="form-control-static">
{{order.customer_ip}}&nbsp;&nbsp;<a role="button" ng-click="getPayLocation(order.customer_ip)">查询地区</a><span ng-if="pay_location"> : {{pay_location}}</span>
</p>
</div>
</div>
@ -128,6 +130,12 @@
<p class="form-control-static" ng-bind="order.clearing_amount|currency:'AUD '"></p>
</div>
</div>
<div class="form-group" ng-if="order.status>=5">
<label class="control-label col-xs-3">Gateway</label>
<div class="col-xs-9">
<p class="form-control-static" ng-bind="order.gateway|tradeGateway"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-3">Create Time</label>
<div class="col-xs-9">

@ -51,7 +51,7 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
url: '/phone_top_up',
templateUrl: '/static/config/devtools/templates/phone_top_up.html',
controller: 'phonetopupCtrl'
});
})
}]);
app.controller('devManualRefundCtrl', ['$scope', '$http', 'commonDialog', function ($scope, $http, commonDialog) {
$scope.sendRefund = function () {
@ -302,5 +302,6 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
})
}
}]);
return app;
});

@ -124,11 +124,23 @@ define(['angular', 'uiRouter', 'uiBootstrap', 'angularEcharts'], function (angul
function loadAnalysis() {
$http.get('/dashboard/system/common_analysis_1', {params: $scope.currentScale.params()}).then(function (resp) {
// $scope.analysis.new_partners = resp.data.new_partners;
// $scope.analysis.total_partners = resp.data.total_partners;
// $scope.analysis.traded_partners = resp.data.traded_partners;
$scope.analysis.trade_amount = resp.data.trade_amount;
$scope.analysis.trade_count = resp.data.trade_count;
// $scope.analysis.top_amount_order = resp.data.top_amount_order;
// $scope.analysis.trade_count = resp.data.trade_count;
// $scope.analysis.total_customers = resp.data.total_customers;
// $scope.analysis.new_customers = resp.data.total_customers-resp.data.old_customers;
// $scope.analysis.old_customers = resp.data.old_customers;
});
$http.get('/dashboard/system/common_analysis_3', {params: $scope.currentScale.params()}).then(function (resp) {
$scope.analysis.new_partners = resp.data.new_partners;
$scope.analysis.total_partners = resp.data.total_partners;
$scope.analysis.traded_partners = resp.data.traded_partners;
$scope.analysis.trade_amount = resp.data.trade_amount;
$scope.analysis.trade_count = resp.data.trade_count;
// $scope.analysis.top_amount_order = resp.data.top_amount_order;
// $scope.analysis.trade_count = resp.data.trade_count;
@ -136,6 +148,7 @@ define(['angular', 'uiRouter', 'uiBootstrap', 'angularEcharts'], function (angul
// $scope.analysis.new_customers = resp.data.total_customers-resp.data.old_customers;
// $scope.analysis.old_customers = resp.data.old_customers;
});
$http.get('/dashboard/system/common_analysis_2', {params: $scope.currentScale.params()}).then(function (resp) {
// $scope.analysis.new_partners = resp.data.new_partners;
// $scope.analysis.total_partners = resp.data.total_partners;

@ -0,0 +1,115 @@
define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootSwitch', 'ngFileUpload', 'uiSelect'], function (angular) {
'use strict';
var app = angular.module('merchantIdManage', ['ui.bootstrap', 'ui.router', 'frapontillo.bootstrap-switch', 'ngFileUpload', 'ui.select']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('merchant_id_manage', {
url: '/merchant_id/manage',
templateUrl: '/static/payment/merchantid/templates/merchant_id_manage.html',
controller: 'merchantIdManageCtrl',
data: {label: '商户号列表'}
})
}]);
app.controller('merchantIdManageCtrl', ['$scope', '$state', '$http', '$uibModal', 'commonDialog', function ($scope, $state, $http,$uibModal,commonDialog) {
$scope.pagination = {};
$scope.params = {};
$scope.isCollapsed = true;
$scope.loadClient = function () {
$scope.client_loading = true;
$http.get('/sys/merchant_id').then(function (resp) {
$scope.clientsMap = resp.data;
$scope.client_loading = false;
});
};
$scope.loadClient();
$scope.loadNotTradeClient = function () {
$http.get('/sys/merchant_id/trade').then(function (resp) {
$scope.notTradeClientsMap = resp.data.merchant_id_map;
$scope.refresh_time = resp.data.refresh_time;
$scope.disable_button = false;
});
};
$scope.loadNotTradeClient();
$scope.loadTempSubMerchantId = function () {
var params = angular.copy($scope.params);
if(!params.sub_merchant_id){
delete params.sub_merchant_id;
}
$http.get('/sys/merchant_id/common_sub_merchant_id',{params: params}).then(function (resp) {
$scope.subMerchantIdList= resp.data;
});
};
$scope.loadTempSubMerchantId();
$scope.showClient = function (sub_merchant_id) {
$uibModal.open({
templateUrl: '/static/payment/merchantid/templates/client_sub_merchant_id.html',
controller: 'showClientsCtrl',
resolve: {
clients: ['$http', function ($http) {
return $http.get('/sys/merchant_id/'+sub_merchant_id);
}]
},
size: 'sm'
})
};
$scope.refresh = function () {
$scope.disable_button = true;
$http.post('/sys/merchant_id/refresh').then(function (resp) {
$scope.loadNotTradeClient();
});
};
$scope.save = function () {
$uibModal.open({
templateUrl: '/static/payment/merchantid/templates/new_common_sub_merchant_id.html',
controller: 'newCommonSubMerchantIdCtrl'
}).result.then(function () {
$scope.loadTempSubMerchantId()
})
}
$scope.disable = function (sub_merchant_id) {
$http.put('/sys/merchant_id/common_sub_merchant_id/'+sub_merchant_id).then(function (resp) {
commonDialog.alert({title: 'Success', content: 'Success', type: 'success'});
$scope.loadTempSubMerchantId();
},function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
});
}
}]);
app.controller('showClientsCtrl', ['$scope', '$http','clients', function ($scope, $http,clients) {
$scope.clients = clients.data;
}]);
app.controller('newCommonSubMerchantIdCtrl', ['$scope', '$http','commonDialog','$state', function ($scope, $http,commonDialog,$state) {
$scope.params = {};
$scope.saveSubMerchantId = function () {
var params = angular.copy($scope.params);
$http.post('/sys/merchant_id/common_sub_merchant_id/'+params.sub_merchant_id).then(function () {
$scope.$close();
commonDialog.alert({title: 'Success', content: '保存成功', type: 'success'});
},function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
});
};
}]);
app.filter('choose_merchant_id', function () {
return function (value) {
switch (value + '') {
case '1307485301':
return '1307485301(Tunnel Show1)';
case '1431999902':
return '1431999902(Tunnel Show2)';
case '1487387142':
return '1487387142(NAP)';
case '':
return ''
}
}
});
return app;
});

@ -0,0 +1,26 @@
<style>
.padding-size{
padding-top: 5px;
padding-right: 5px;
padding-bottom: 5px;
padding-left: 15px;
}
.padding-top-size{
padding-top: 10px;
}
</style>
<div class="modal-header padding-size">
<h5>Clients</h5>
</div>
<div class="modal-body" padding-top-size>
<div>
<a ng-repeat="client in clients track by $index" ng-show="$index<clients.length-1"
ui-sref="partners.detail({clientMoniker:client.client_moniker})">
{{client.client_moniker}}<span class="text-black">,</span>&nbsp;
</a>
<a ng-repeat="client in clients" ng-if="$last"
ui-sref="partners.detail({clientMoniker:client.client_moniker})">
{{client.client_moniker}}
</a>
</div>
</div>

@ -0,0 +1,156 @@
<style>
.cursor {
cursor: pointer;
}
.div-display{
display: none;
}
.i-rotate_90{
animation:rotate_90 1s forwards;
-webkit-animation:rotate_90 1s forwards; /* Safari and Chrome */
}
@keyframes rotate_90
{
from {transform:rotate(0deg);}
to {transform:rotate(90deg);}
}
@-webkit-keyframes rotate_90 /* Safari and Chrome */
{
from {-webkit-transform:rotate(0deg);}
to {-webkit-transform:rotate(90deg);}
}
</style>
<div ui-view>
<section class="content-header">
<h1>Merchant Id Manage</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-sitemap"></i> Payment
</li>
<li class="active">Merchant Id Manage</li>
</ol>
</section>
<div class="content">
<div class="box box-warning">
<div class="box-body">
<uib-tabset>
<uib-tab heading="商户号列表">
<loadingbar ng-if="client_loading"></loadingbar>
<div class="col-sm-12 col-xs-12">
<div style="margin-top: 5px">
<div class="list-group col-sm-12 col-xs-12" ng-repeat="(key,clients) in clientsMap">
<a class="list-group-item active col-sm-12 col-xs-12">
{{key|choose_merchant_id}}
<span ng-show="clients.length>59" class="small-box-footer cursor pull-right" ng-click="isCollapsed = !isCollapsed"><span ng-if="clients.length>59">更多 <i class="fa fa-arrow-circle-right" ng-class="{'i-rotate_90':!isCollapsed}"></i></span></span>
</a>
<a class="list-group-item col-sm-2 col-xs-6 cursor"
ng-repeat="client in clients | orderBy:'client_count':true"
ng--click="showClient(client.sub_merchant_id);" ng-if="$index<60">
<span>
{{client.sub_merchant_id}}&nbsp;<i class="fa fa-clock-o text-danger"
title="Using temp Sub Merchant ID"
ng-if="client.temp_sub_merchant"></i></span>
<span class="badge" aria-hidden="true" title="show detail">{{client.client_count}}</span>
</a>
<a class="list-group-item col-sm-2 col-xs-6 cursor" ng-hide="isCollapsed"
ng-repeat="client in clients | orderBy:'client_count':true"
ng--click="showClient(client.sub_merchant_id);" ng-if="$index>59">
<span>
{{client.sub_merchant_id}}&nbsp;<i class="fa fa-clock-o text-danger"
title="Using temp Sub Merchant ID"
ng-if="client.temp_sub_merchant"></i></span>
<span class="badge" aria-hidden="true" title="show detail">{{client.client_count}}</span>
</a>
</div>
</div>
</div>
</uib-tab>
<uib-tab heading="近25天未交易商户号">
<div class="box-body">
<div class="col-sm-12 col-xs-12" style="padding-right: 30px;margin-bottom: 5px">
<div class="pull-right">
<span ng-if="refresh_time">
<span>上次刷新时间:</span><span><em><b>{{refresh_time}}</b></em></span>
</span>&nbsp;&nbsp;
<a role="button" class="btn btn-primary" title="refresh" ng-click="refresh()" ng-class="{disabled:disable_button}">
<i class="glyphicon glyphicon-refresh"
title="refresh"></i>
</a>
</div>
</div>
<div class="col-sm-12 col-xs-12">
<loadingbar ng-if="disable_button"></loadingbar>
<div>
<div class="list-group col-sm-12 col-xs-12"
ng-repeat="(key,clients) in notTradeClientsMap">
<a class="list-group-item active col-sm-12 col-xs-12">
{{key|choose_merchant_id}}
<span ng-show="clients.length>59" class="small-box-footer cursor pull-right" ng-click="isCollapsed = !isCollapsed">更多 <i class="fa fa-arrow-circle-right" ng-class="{'i-rotate_90':!isCollapsed}"></i></span>
</a>
<a class="list-group-item col-sm-2 col-xs-6 cursor"
ng-repeat="client in clients | orderBy:'client_count':true"
ng--click="showClient(client.sub_merchant_id)" ng-if="$index<60">
<span>{{client.sub_merchant_id}}&nbsp;<i class="fa fa-clock-o text-danger"
title="Temp Sub Merchant ID"
ng-if="client.temp_sub_merchant"></i></span>
<span class="badge" aria-hidden="true" title="show detail">{{client.client_count}}</span>
</a>
<a class="list-group-item col-sm-2 col-xs-6 cursor" ng-hide="isCollapsed"
ng-repeat="client in clients | orderBy:'client_count':true"
ng--click="showClient(client.sub_merchant_id)" ng-if="$index>59">
<span>{{client.sub_merchant_id}}&nbsp;<i class="fa fa-clock-o text-danger"
title="Temp Sub Merchant ID"
ng-if="client.temp_sub_merchant"></i></span>
<span class="badge" aria-hidden="true" title="show detail">{{client.client_count}}</span>
</a>
</div>
</div>
</div>
</div>
</uib-tab>
<uib-tab heading="通用子商户号">
<div class="box-body table-responsive">
<div class="col-sm-12 col-xs-6">
<a role="button" class="btn btn-primary pull-right" title="Add Sub Merchant Id" ng-click="save()">
<i class="fa fa-plus"></i>
Add
</a>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Merchant Id</th>
<th>Sub Merchant Id</th>
<th>Operator</th>
<th>Create Time</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in subMerchantIdList">
<td ng-bind="client.merchant_id"></td>
<td>
{{client.sub_merchant_id}}
<i class="fa fa-clock-o text-danger"
title="Temp Sub Merchant ID"></i>
</td>
<td ng-bind="client.operator"></td>
<td ng-bind="client.create_time"></td>
<td>
<a class="text-bold text-danger" role="button" ng-click="disable(client.sub_merchant_id)">Disable</a>
</td>
</tr>
</tbody>
</table>
</div>
</uib-tab>
</uib-tabset>
</div>
</div>
</div>
</div>

@ -0,0 +1,24 @@
<section class="content-header">
<h1>New Common Sub Merchant ID</h1>
</section>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="box-solid">
<div class="box box-warning">
<div class="box-header">
<form role="form" style="margin:0px auto;width: 50%">
<div class="form-group">
<label>Sub Merchant ID</label>
<input ng-model="params.sub_merchant_id" class="form-control" type="text" />
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" ng-click="saveSubMerchantId()">save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>

@ -385,6 +385,17 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
alert("Logo is necessary!");
return;
}
if($scope.partner.partner_type == 'photo'){
if (!$scope.partner.company_photo) {
alert('Shop Photo1 is necessary');
return;
}
if (!$scope.partner.store_photo) {
alert('Shop Photo2 is necessary');
return;
}
}
if ($scope.partner.referrer_id) {
$scope.referrers.forEach(function (e) {
if ($scope.partner.referrer_id == e.org_id) {
@ -393,6 +404,10 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}
})
}
if(!window.frames['merchant_detail'].merchant_location){
alert("Please Locate Merchant's Location");
return;
}
$http.post('/sys/partners', $scope.partner).then(function (resp) {
commonDialog.alert({title: 'Success', content: 'Register new partner successfully', type: 'success'});
$scope.updateMerchantLocation();
@ -423,18 +438,36 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.uploadShopPhoto = function (file) {
if (file != null) {
$scope.photoProgress = {value: 0};
$scope.shopPhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
$scope.partner.company_photo = resp.data.url;
}, function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.photoProgress.value = parseInt(100 * evt.loaded / evt.total);
$scope.shopPhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadStorePhoto = function (file) {
if (file != null) {
$scope.storePhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.storePhotoProgress;
$scope.partner.store_photo = resp.data.url;
}, function (resp) {
delete $scope.storePhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.storePhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
@ -444,14 +477,18 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
if (params) {
$http.put('/sys/partners/modify/' + $scope.partner.client_moniker + '/location', params).then(function () {
});
} else {
alert("Please Locate Merchant's Location");
}
}
}]);
app.controller('partnerDetailCtrl', ['$scope', '$http', '$state', '$uibModal', '$rootScope', 'Upload', 'commonDialog', 'partner', function ($scope, $http, $state, $uibModal, $rootScope, Upload, commonDialog, partner) {
$scope.init = {wechat_compliance: false, local_merchant: false};
$scope.partner = partner.data;
var website = partner.data.company_website;
if (website!=null){
if (website.indexOf('http')!=0){
$scope.partner.company_website= 'http://'+angular.copy(website);
}
}
$scope.showDBUsers = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/bd_user').then(function (resp) {
$scope.partner.client_bds = resp.data;
@ -895,6 +932,17 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
alert('suburb can not contain two and more continuous space characters');
return;
}
if($scope.partner.partner_type == 'photo'){
if (!$scope.partner.company_photo) {
alert('Shop Photo1 is necessary');
return;
}
if (!$scope.partner.store_photo) {
alert('Shop Photo2 is necessary');
return;
}
}
if ($scope.partner.acn && $scope.partner.business_structure == 'Company') {
if ($scope.partner.acn.length != 9) {
alert('Acn is not valid');
@ -908,11 +956,14 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}
})
}
$scope.updateMerchantLocation();
var content = '';
if (!origin_referrer_id && $scope.partner.referrer_id) {
content = 'Update partner info successfully,But You Had add new Referrer,Please Change the BD Commission Proportion!';
}
if(!window.frames['merchant_detail'].merchant_location){
alert("Please Locate Merchant Location!");
return;
}
$http.put('/sys/partners/' + $scope.partner.client_moniker, $scope.partner).then(function () {
if (content != '') {
commonDialog.alert({
@ -927,6 +978,7 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
type: 'success'
});
}
$scope.updateMerchantLocation();
$scope.loadPartners();
$state.go('^.detail', {clientMoniker: $scope.partner.client_moniker}, {reload: true});
}, function (resp) {
@ -954,18 +1006,36 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.uploadShopPhoto = function (file) {
if (file != null) {
$scope.photoProgress = {value: 0};
$scope.shopPhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
$scope.partner.company_photo = resp.data.url;
}, function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.shopPhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadStorePhoto = function (file) {
if (file != null) {
$scope.storePhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.storePhotoProgress;
$scope.partner.store_photo = resp.data.url;
}, function (resp) {
delete $scope.storePhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.photoProgress.value = parseInt(100 * evt.loaded / evt.total);
$scope.storePhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
@ -982,16 +1052,10 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
if (params) {
$http.put('/sys/partners/modify/' + $scope.partner.client_moniker + '/location', params).then(function () {
});
} else {
commonDialog.alert({
title: 'Warning',
content: 'Please Locate Merchant Location',
type: 'error'
});
}
}
}]);
app.controller('partnerPaymentInfoCtrl', ['$scope', '$http', '$state', 'commonDialog', function ($scope, $http, $state, commonDialog) {
app.controller('partnerPaymentInfoCtrl', ['$scope', '$http', '$state', 'commonDialog','$uibModal', function ($scope, $http, $state, commonDialog,$uibModal) {
$scope.loadPartnerPaymentInfo = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker).then(function (resp) {
$scope.paymentInfo = resp.data;
@ -1010,6 +1074,21 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.reloadQRCode();
$scope.loadPartnerPaymentInfo();
$scope.showSubMerchantLogs = function () {
$uibModal.open({
templateUrl: '/static/payment/partner/templates/client_sub_merchant_id_log.html',
controller: 'clientSubMerchantIdLogCtrl',
size: 'lg',
resolve: {
logs: ['$http', function ($http) {
return $http.get('/sys/partners/'+$scope.partner.client_moniker+'/get_sub_merchant_id_logs');
}]
}
}).result.then(function () {
$scope.loadSubClients();
});
};
$scope.saveMaxOrderAmount = function (limit) {
if (limit != null && isNaN(limit)) {
commonDialog.alert({title: 'Error', content: 'Your input is not a number!', type: 'error'});
@ -1123,7 +1202,25 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
})
})
};
$scope.init = {jsapi: false, gateway: false, offline: false, refund: false, channel: {}};
$scope.init = {jsapi: false, gateway: false, offline: false, refund: false,common_sub_merchant_id:false, channel: {}};
$scope.switchCommonSubMerchantId = function () {
if (!$scope.paymentInfo) {
return;
}
if (!$scope.init.common_sub_merchant_id) {
$scope.init.common_sub_merchant_id = true;
return;
}
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/common_sub_merchant_id', {allow: $scope.paymentInfo.common_sub_merchant_id}).then(function () {
$scope.loadPartnerPaymentInfo();
}, function (resp) {
commonDialog.alert({
title: 'Failed to change common_sub_merchant_id permission status',
content: resp.data.message,
type: 'error'
})
})
};
$scope.toggleChannel = function (channel) {
if (!channel) {
return;
@ -1308,6 +1405,9 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
};
}]);
app.controller('clientSubMerchantIdLogCtrl', ['$scope', '$http', 'logs', function ($scope, $http, logs) {
$scope.logs = logs.data;
}]);
app.controller('partnerSubCtrl', ['$scope', '$http', '$uibModal', function ($scope, $http, $uibModal) {
$scope.newSubClient = function () {
$uibModal.open({
@ -1395,6 +1495,10 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
};
$scope.getRates();
$scope.saveBankAccount = function () {
if(isNaN($scope.bankaccount.account_no)){
alert("Account No应输入数字!");
return;
};
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/bank_account', $scope.bankaccount).then(function () {
$scope.getBankAccount();
}, function (resp) {
@ -1723,6 +1827,24 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
return;
}
}
if (!$scope.partner.logo_url) {
alert("Logo is necessary!");
return;
}
if($scope.partner.partner_type == 'photo'){
if (!$scope.partner.company_photo) {
alert('Shop Photo1 is necessary');
return;
}
if (!$scope.partner.store_photo) {
alert('Shop Photo2 is necessary');
return;
}
}
if(!window.frames['merchant_detail'].merchant_location){
alert("Please Locate Merchant Location!");
return;
}
$http.post('/sys/partners/' + clientMoniker + '/sub_clients', $scope.partner).then(function () {
$scope.updateMerchantLocation();
$scope.$close();
@ -1751,18 +1873,36 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.uploadShopPhoto = function (file) {
if (file != null) {
$scope.photoProgress = {value: 0};
$scope.shopPhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
$scope.partner.company_photo = resp.data.url;
}, function (resp) {
delete $scope.photoProgress;
delete $scope.shopPhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.shopPhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadStorePhoto = function (file) {
if (file != null) {
$scope.storePhotoProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.storePhotoProgress;
$scope.partner.store_photo = resp.data.url;
}, function (resp) {
delete $scope.storePhotoProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.photoProgress.value = parseInt(100 * evt.loaded / evt.total);
$scope.storePhotoProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
@ -1771,12 +1911,6 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
if (params) {
$http.put('/sys/partners/modify/' + $scope.partner.client_moniker + '/location', params).then(function () {
});
} else {
commonDialog.alert({
title: 'Warning',
content: 'Please Locate Merchant Location',
type: 'error'
});
}
}
}]);

@ -1,3 +1,9 @@
<style>
.img-size{
max-height: 100px;
margin-left: 20px;
}
</style>
<section class="content-header">
<h1>New Partner</h1>
<ol class="breadcrumb">
@ -127,7 +133,7 @@
</div>
<uib-progressbar value="logoProgress.value"
ng-if="logoProgress"></uib-progressbar>
<img ng-src="{{partner.logo_url}}" class="col-sm-3">
<img ng-src="{{partner.logo_url}}" ng-if="partner.logo_url" style="height: 100px;">
</div>
</div>
<!--<div class="form-group"-->
@ -210,6 +216,8 @@
a photo of shop is
required while an online store shall choose
companyWebsite</p>
<p class="small text-info">
只要有可能产生线下交易商户静态码、POS就必须上传照片否则支付宝会禁止交易</p>
<div ng-messages="partnerForm.partner_type.$error"
ng-if="partnerForm.partner_type.$dirty">
<p class="small text-danger" ng-message="required">Required
@ -219,19 +227,32 @@
</div>
<div class="form-group" ng-if="partner.partner_type == 'photo'">
<label class="control-label col-sm-2">* Shop Photo</label>
<div class="col-sm-8">
<div class="form-control-static">
<div class="col-sm-4">
<div class="form-control-static"><em>1:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadShopPhoto($file)" accept="image/*"
ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo
<i class="fa fa-upload"></i> Upload Shop Photo1
</button>
</div>
<uib-progressbar value="shopPhotoProgress.value"
ng-if="shopPhotoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" ng-if="partner.company_photo" class="thumbnail img-size col-sm-9">
</div>
<div class="col-sm-4">
<div class="form-control-static"><em>2:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadStorePhoto($file)" accept="image/*"
ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo2
</button>
</div>
<uib-progressbar value="photoProgress.value"
ng-if="photoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" class="col-sm-4">
<uib-progressbar value="storePhotoProgress.value"
ng-if="storePhotoProgress"></uib-progressbar>
<img ng-src="{{partner.store_photo}}" ng-if="partner.store_photo" class="thumbnail img-size col-sm-9">
</div>
</div>
<div class="form-group" ng-if="partner.partner_type == 'companyWebsite'"
ng-class="{'has-error':partnerForm.company_website.$invalid && partnerForm.company_website.$dirty}">
<label class="control-label col-sm-2" for="company_website-input">*
@ -350,6 +371,45 @@
</div>
</div>
<!--end 商户基本资料-->
<div class="panel panel-default">
<div class="panel-heading">Alipay Information &nbsp;<em class="small"><b>(Optional)</b></em></div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">
Business Hours</label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.business_hours">
<p class="small text-info">
eg:Monday-Friday 09:00-20:00,Saturday-Sunday 10:00-22:00</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Tag<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_tag">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Introduction<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<textarea class="form-control" ng-model="partner.merchant_introduction"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Video Introduction<br><em class="small">(youtube link)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_video_url">
<p class="small text-info">eg:https://www.baidu.com</p>
</div>
</div>
</div>
</div>
</div>
<!--支付宝资料-->
<div class="panel panel-default">
<div class="panel-heading">Contact Information</div>
<div class="panel-body">

@ -1,3 +1,9 @@
<style>
.img-size{
max-height: 100px;
margin-left: 20px;
}
</style>
<div class="modal-header bg-success">
<h4>New Sub Partner</h4>
</div>
@ -169,6 +175,8 @@
</select>
<p class="small text-info">If the partner is a offline shop then a photo of shop is
required while an online store shall choose companyWebsite</p>
<p class="small text-info">
只要有可能产生线下交易商户静态码、POS就必须上传照片否则支付宝会禁止交易</p>
<div ng-messages="partnerForm.partner_type.$error"
ng-if="partnerForm.partner_type.$dirty">
<p class="small text-danger" ng-message="required">Required Field</p>
@ -177,16 +185,29 @@
</div>
<div class="form-group" ng-if="partner.partner_type == 'photo'">
<label class="control-label col-sm-2">* Shop Photo</label>
<div class="col-sm-8">
<div class="form-control-static">
<div class="col-sm-4">
<div class="form-control-static"><em>1:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadShopPhoto($file)" accept="image/*"
ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo1
</button>
</div>
<uib-progressbar value="shopPhotoProgress.value"
ng-if="shopPhotoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" ng-if="partner.company_photo" class="thumbnail img-size col-sm-9">
</div>
<div class="col-sm-4">
<div class="form-control-static"><em>2:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadShopPhoto($file)" accept="image/*" ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo
ngf-select="uploadStorePhoto($file)" accept="image/*"
ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo2
</button>
</div>
<uib-progressbar value="photoProgress.value"
ng-if="photoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" class="col-sm-4">
<uib-progressbar value="storePhotoProgress.value"
ng-if="storePhotoProgress"></uib-progressbar>
<img ng-src="{{partner.store_photo}}" ng-if="partner.store_photo" class="thumbnail img-size col-sm-9">
</div>
</div>
<div class="form-group" ng-if="partner.partner_type == 'companyWebsite'"
@ -282,6 +303,45 @@
</div>
</div>
<!--end 商户基本资料-->
<div class="panel panel-default">
<div class="panel-heading">Alipay Information &nbsp;<em class="small"><b>(Optional)</b></em></div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">
Business Hours</label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.business_hours">
<p class="small text-info">
eg:Monday-Friday 09:00-20:00,Saturday-Sunday 10:00-22:00</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Tag<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_tag">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Introduction<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<textarea class="form-control" ng-model="partner.merchant_introduction"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Video Introduction<br><em class="small">(youtube link)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_video_url">
<p class="small text-info">eg:https://www.baidu.com</p>
</div>
</div>
</div>
</div>
</div>
<!--支付宝资料-->
<div class="panel panel-default">
<div class="panel-heading">Contact Information</div>
<div class="panel-body">

@ -115,7 +115,7 @@
<div class="col-sm-10">
<a class="form-control-static" target="_blank" ng-bind="partner.company_website"
ng-href="{{partner.company_website}}"></a>
href="https://{{partner.company_website}}" ></a>
</div>
</div>
<div class="form-group">

@ -0,0 +1,41 @@
<section class="content-header">
<h1>Sub Merchant Id Logs</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-users"></i> Configuration
</li>
<li class="active">logs</li>
</ol>
</section>
<section class="content">
<div class="box-solid">
<div class="box box-warning">
<div class="box-body">
<div class="row">
<div class="col-sm-12">
<div class="col-sm-12 table-responsive">
<table class="table table-striped table-bordered table-hover" ng-if="logs.length>0">
<thead>
<tr>
<th>Sub Merchant Id Before</th>
<th>Sub Merchant Id After</th>
<th>Operator</th>
<th>Create Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="log in logs">
<td ng-bind="log.sub_merchant_id_before"></td>
<td ng-bind="log.sub_merchant_id_after"></td>
<td ng-bind="log.operator"></td>
<td ng-bind="log.create_time"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

@ -28,6 +28,10 @@
width: 95%;
float: left;
}
.img-size{
height: 100px;
margin-left: 20px;
}
</style>
<section class="content-header">
<h1>
@ -304,7 +308,7 @@
<div class="form-group">
<label class="control-label col-sm-2">Logo</label>
<div class="col-sm-10">
<img ng-src="{{partner.logo_url}}" class="col-sm-3 col-xs-5">
<img ng-src="{{partner.logo_url}}" style="max-height: 100px;">
</div>
</div>
<div class="form-group" ng-if="partner.abn">
@ -336,11 +340,18 @@
</div>
<div class="form-group" ng-if="partner.company_photo">
<label class="control-label col-sm-2">Shop Photo</label>
<div class="col-sm-10">
<div class="col-sm-3 col-xs-5">
<div class="col-sm-3 col-xs-5"><em>1:</em>&nbsp;
<div>
<a class="thumbnail" target="_blank" ng-href="{{partner.company_photo}}">
<img ng-src="{{partner.company_photo}}">
<img ng-src="{{partner.company_photo}}" style="max-height: 100px">
</a>
</div>
</div>
<div class="col-sm-3 col-xs-5" ng-if="partner.store_photo"><em>2:</em>&nbsp;
<div>
<a class="thumbnail" target="_blank" ng-href="{{partner.store_photo}}" >
<img ng-src="{{partner.store_photo}}" style="max-height: 100px">
</a>
</div>
</div>
@ -350,7 +361,7 @@
<div class="col-sm-10">
<a class="form-control-static" target="_blank" ng-bind="partner.company_website"
ng-href="{{partner.company_website}}"></a>
href="{{partner.company_website}}"></a>
</div>
</div>
<div class="form-group">
@ -441,6 +452,42 @@
</div>
</div>
<!--end 商户基本资料-->
<!--支付宝资料-->
<div class="panel panel-default">
<div class="panel-heading">Alipay Information &nbsp;<em class="small"><b>(Optional)</b></em></div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">
Business Hours</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.business_hours"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Tag</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.merchant_tag"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Introduction</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.merchant_introduction"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Introduction<br><em class="small">(Video connection)</em></label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.merchant_video_url"></p>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Partner Contact Information</div>
<div class="panel-body">
@ -650,8 +697,10 @@
<div class="form-group">
<label class="control-label col-sm-2">Alipay Category</label>
<div class="col-sm-10">
<p class="form-control-static industry-p"
ng-bind="partner.alipayindustry|partner_alipay_industry"></p>
<p class="form-control-static industry-p"ng-if="partner.alipayindustry">
{{partner.alipayindustry|partner_alipay_industry}}
&nbsp;&nbsp;&nbsp;({{partner.alipayindustry}})
</p>
<i class="fa fa-check-square-o check-i" aria-hidden="true"
ng-if="$root.complianceCheck.clientInfo"></i>
</div>

@ -1,3 +1,9 @@
<style>
.img-size{
max-height: 100px;
margin-left: 20px;
}
</style>
<section class="content-header">
<h1 ng-bind="partner.short_name"></h1>
<ol class="breadcrumb">
@ -90,7 +96,7 @@
</button>
</div>
<uib-progressbar value="logoProgress.value" ng-if="logoProgress"></uib-progressbar>
<img ng-src="{{partner.logo_url}}" class="col-sm-3">
<img ng-src="{{partner.logo_url}}" ng-if="partner.logo_url" style="height: 100px;">
</div>
</div>
<!--<div class="form-group"-->
@ -160,6 +166,8 @@
</select>
<p class="small text-info">If the partner is a offline shop then a photo of shop is
required while an online store shall choose company website</p>
<p class="small text-info">
只要有可能产生线下交易商户静态码、POS就必须上传照片否则支付宝会禁止交易</p>
<div ng-messages="partnerForm.partner_type.$error"
ng-if="partnerForm.partner_type.$dirty">
<p class="small text-danger" ng-message="required">Required Field</p>
@ -169,16 +177,28 @@
<div class="form-group"
ng-if="partner.partner_type == 'photo' && (!partner.parent_client_id || ('00110'|withRole))">
<label class="control-label col-sm-2">* Shop Photo</label>
<div class="col-sm-8">
<div class="form-control-static">
<div class="col-sm-5">
<div class="form-control-static"><em>1:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadShopPhoto($file)" accept="image/*" ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo
<i class="fa fa-upload"></i> Upload Shop Photo1
</button>
</div>
<uib-progressbar value="shopPhotoProgress.value"
ng-if="shopPhotoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" ng-if="partner.company_photo" class="thumbnail img-size col-sm-9">
</div>
<div class="col-sm-5">
<div class="form-control-static"><em>2:</em>&nbsp;
<button class="btn btn-primary" type="button"
ngf-select="uploadStorePhoto($file)" accept="image/*"
ngf-max-size="2MB">
<i class="fa fa-upload"></i> Upload Shop Photo2
</button>
</div>
<uib-progressbar value="photoProgress.value"
ng-if="photoProgress"></uib-progressbar>
<img ng-src="{{partner.company_photo}}" class="col-sm-4">
<uib-progressbar value="storePhotoProgress.value"
ng-if="storePhotoProgress"></uib-progressbar>
<img ng-src="{{partner.store_photo}}" ng-if="partner.store_photo" class="thumbnail img-size col-sm-9">
</div>
</div>
<div class="form-group"
@ -243,6 +263,45 @@
</div>
</div>
<!--end 商户基本资料-->
<div class="panel panel-default">
<div class="panel-heading">Alipay Information &nbsp; <em class="small"><b>(Optional)</b></em></div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">
Business Hours</label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.business_hours">
<p class="small text-info">
eg:Monday-Friday 09:00-20:00,Saturday-Sunday 10:00-22:00</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Tag<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_tag">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Merchant Introduction<em class="small">(Chinese)</em></label>
<div class="col-sm-8">
<textarea class="form-control" ng-model="partner.merchant_introduction"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">
Video Introduction<br><em class="small">(youtube link)</em></label>
<div class="col-sm-8">
<input type="text" class="form-control" ng-model="partner.merchant_video_url">
<p class="small text-info">eg:https://www.baidu.com</p>
</div>
</div>
</div>
</div>
</div>
<!--支付宝资料-->
<div class="panel panel-default">
<div class="panel-heading">Contact Information</div>
<div class="panel-body">
@ -294,6 +353,7 @@
</div>
</div>
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>

@ -12,6 +12,16 @@
<a role="button" ng-click="ctrl.editSubMerchant=true" ng-if="'011'|withRole"><i class="fa fa-edit"></i></a>
<i class="fa fa-clock-o text-danger" title="Using temp Sub Merchant ID" ng-if="paymentInfo.temp_sub_merchant"></i>
&nbsp;&nbsp;<span class="small" ng-if="('10'|withRole) &&paymentInfo.sub_merchant_id&&paymentInfo.merchant_id"><b>Merchant ID</b>:{{paymentInfo.merchant_id | choose_merchant_id}}</span>
&nbsp;&nbsp;
<span class="small"
ng-if="('10'|withRole) &&paymentInfo.sub_merchant_id&&paymentInfo.sub_merchant_id_log">
<a class="text-primary" role="button" title="modify logs"
ng-click="showSubMerchantLogs(sub_merchant_id_logs)">
<span class="pull-right-container">
<span class="label label-primary">history</span>
</span>
</a>
</span>
</p>
<div class="input-group" ng-if="ctrl.editSubMerchant">
<input type="text" class="form-control" ng-model="paymentInfo.sub_merchant_id"
@ -29,6 +39,12 @@
</div>
</div>
</div>
<div class="form-group" ng-if="'10'|withRole">
<label class="col-sm-3 control-label">Common Sub Merchant Id</label>
<div class="col-xs-9">
<input type="checkbox" ng-model="paymentInfo.common_sub_merchant_id" bs-switch switch-change="switchCommonSubMerchantId()">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Max Order Amount</label>
<div class="col-sm-9">

@ -212,13 +212,13 @@
<span class="info-box-text" >Input Amount</span>
<span class="info-box-number box-number_font" style="margin-bottom: -3px;" ng-class="{line_height_:!analysis.pre_display_amount}"
ng-bind="analysis.display_amount|currency:'AUD '"></span>
<span style="font-size: 8px;line-height: 8px" ng-if="analysis.pre_display_amount">
<span style="font-size: 10px;line-height: 10px" ng-if="analysis.pre_display_amount">
( {{analysis.pre_display_amount | currency:'pre authorization '}} )
</span>
<span class="info-box-number box-number_font" style="margin-bottom: -3px;"
ng-if="analysis.cny_display_amount"
ng-bind="analysis.cny_display_amount|currency:'CNY '"></span>
<span style="font-size: 8px;line-height: 8px" ng-if="analysis.pre_cny_display_amount">
<span style="font-size: 10px;line-height: 10px" ng-if="analysis.pre_cny_display_amount">
( {{analysis.pre_cny_display_amount | currency:'pre authorization '}} )
</span>
</div>
@ -277,7 +277,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="trade in tradeLogs" ng-class="{'tr_refund':trade.trans_type=='refund','tr_clearing':trade.trans_type=='clearing'}">
<tr ng-repeat="trade in tradeLogs" ng-class="{'tr_refund':trade.trans_type=='refund','tr_clearing':trade.trans_type=='clearing',warning:trade.clearing_status==2}">
<td ng-bind="trade.transaction_time||'NOT PROVIDED'"></td>
<td>
<img src="/static/images/wechatpay_sign.png"

@ -185,7 +185,6 @@
<th>Currency</th>
<th>Input Amount</th>
<th>Total Amount</th>
<th>Clearing Amount</th>
<th>Surcharge Rate</th>
<th>Surcharge Amount</th>
<th>Tax Amount</th>
@ -202,7 +201,6 @@
<td ng-bind="tr.transaction_currency"></td>
<td ng-bind="tr.display_amount"></td>
<td ng-bind="tr.transaction_amount"></td>
<td ng-bind="tr.clearing_amount"></td>
<td ng-bind="tr.surcharge_rate?(tr.surcharge_rate|percentage:1):report.channels[tr.channel].rate+'%'"></td>
<td ng-bind="tr.total_surcharge?tr.total_surcharge:0"></td>
<td ng-bind="tr.tax_amount"></td>
@ -225,7 +223,7 @@
<th>Transaction Time</th>
<th>Currency</th>
<th>Total Amount</th>
<th>Clearing Amount</th>
<th>Settle Amount</th>
<th>Remark</th>
</tr>
</thead>
@ -235,7 +233,7 @@
<td ng-bind="tr.transaction_time"></td>
<td ng-bind="tr.transaction_currency"></td>
<td ng-bind="tr.transaction_amount"></td>
<td ng-bind="tr.clearing_amount"></td>
<td ng-bind="tr.settle_amount"></td>
<td ng-bind="tr.remark"></td>
</tr>
</tbody>

@ -232,13 +232,13 @@
<span class="info-box-text" >Input Amount</span>
<span class="info-box-number box-number_font" style="margin-bottom: -3px;" ng-class="{line_height_:!analysis.pre_display_amount}"
ng-bind="analysis.display_amount|currency:'AUD '"></span>
<span style="font-size: 8px;line-height: 8px" ng-if="analysis.pre_display_amount">
<span style="font-size: 10px;line-height: 10px" ng-if="analysis.pre_display_amount">
( {{analysis.pre_display_amount | currency:'pre authorization '}} )
</span>
<span class="info-box-number box-number_font" style="margin-bottom: -3px;"
ng-if="analysis.cny_display_amount"
ng-bind="analysis.cny_display_amount|currency:'CNY '"></span>
<span style="font-size: 8px;line-height: 8px" ng-if="analysis.pre_cny_display_amount">
<span style="font-size: 10px;line-height: 10px" ng-if="analysis.pre_cny_display_amount">
( {{analysis.pre_cny_display_amount | currency:'pre authorization '}} )
</span>
</div>

Binary file not shown.

@ -0,0 +1,243 @@
define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootSwitch', 'ngFileUpload'], function (angular) {
'use strict';
var riskType = [
{code: '1', label: 'test1'},
{code: '2', label: 'test2'},
];
var app = angular.module('RiskManagement', ['ui.bootstrap', 'ui.router', 'frapontillo.bootstrap-switch', 'ngFileUpload']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('analysis_monitoring.risk_manager', {
url: '/risk/manage',
templateUrl: '/static/risk/templates/risk.html',
controller: 'RiskManageCtrl',
}).state('analysis_monitoring.risk_orders', {
url: '/risk/{record_id}/orders',
templateUrl: '/static/risk/templates/risk_orders.html',
controller: 'RiskOrderCtrl',
resolve:{
record:['$http','$stateParams', function ($http,$stateParams) {
return $http.get('/sys/risk/records/'+$stateParams.record_id).then(function (res) {
return res.data;
});
}]
}
}).state('analysis_monitoring.risk_history', {
url: '/risk/{record_id}/history',
templateUrl: '/static/risk/templates/risk_history.html',
controller: 'RecordHistoryCtrl',
resolve:{
record:['$http','$stateParams', function ($http,$stateParams) {
return $http.get('/sys/risk/records/'+$stateParams.record_id).then(function (res) {
return res.data;
});
}]
}
}).state('analysis_monitoring.risk_detail', {
url: '/risk/{record_id}/detail',
templateUrl: '/static/risk/templates/risk_detail.html',
controller: 'RecordDetailCtrl',
resolve:{
record:['$http','$stateParams', function ($http,$stateParams) {
return $http.get('/sys/risk/records/'+$stateParams.record_id).then(function (res) {
return res.data;
});
}]
}
});
}]);
app.controller('RiskManageCtrl', ['$scope', '$http', function ($scope, $http){
$scope.params = {};
$scope.pagination = {};
$scope.loadRecords = function (page) {
var params = angular.copy($scope.params);
params.page = page || $scope.pagination.page || 1;
$http.get('/sys/risk/records', {params: params}).then(function (resp) {
$scope.records = resp.data.data;
$scope.pagination = resp.data.pagination;
});
};
$scope.loadRecords(1);
}]);
app.controller('RiskOrderCtrl', ['$scope', '$http', 'record', function ($scope, $http,record) {
$scope.params = {record_id: record.id};
$scope.historyParams = {client_id:record.client_id};
$scope.pagination = {};
$scope.historyPagination = {};
$scope.record = record;
$scope.loadOrders = function (page) {
var params = angular.copy($scope.params);
params.page = page || $scope.pagination.page || 1;
$http.get('/sys/risk/orders',{params: params}).then(function (resp) {
$scope.referenceOrders = resp.data.data;
$scope.pagination = resp.data.pagination;
$scope.historyParams.c_end_time = $scope.orders.pop().create_time;
$scope.loadHistoryOrders(1);
});
};
$scope.loadOrders(1);
$scope.loadHistoryOrders = function (page) {
var historyParams = angular.copy($scope.historyParams);
historyParams.page = page || $scope.historyPagination.page || 1;
$http.get('/sys/risk/orders',{params: historyParams}).then(function (resp) {
$scope.historyOrders = resp.data.data;
$scope.historyPagination = resp.data.pagination;
});
};
}]);
app.controller('RecordHistoryCtrl', ['$scope', '$http','$uibModal', 'commonDialog','record', function ($scope, $http,$uibModal,commonDialog,record) {
$scope.record = record;
$scope.pagination = {};
$scope.params = {client_id:record.client_id,c_end_time:record.create_time};
$scope.listHistory = function (page) {
var params = angular.copy($scope.params);
params.page = page || $scope.pagination.page || 1;
$http.get('/sys/risk/records',{params:params}).then(function (res) {
$scope.histories = res.data.data;
$scope.pagination = res.data.pagination;
})
};
$scope.listHistory(1);
$scope.edit = function () {
$uibModal.open({
templateUrl: '/static/risk/templates/risk_edit.html',
controller: 'RiskRecordHandleCtrl',
resolve:{record_id:function () {
return record.id;
}}
}).result.then(function () {
commonDialog.alert({
title: 'Success',
type: 'success'
});
})
};
$scope.noop = function () {
commonDialog.confirm({
title: 'Confirm',
content: '确定放弃这次预警'
}).then(function () {
$http.put('/sys/risk/records/'+ record.id+'/noop', $scope.params).then(function () {
}).then(function (resp) {
commonDialog.alert({
title: 'Error',
content: resp.data.message,
type: 'Error'
});
})
})
}
}]);
app.controller('RecordDetailCtrl', ['$scope', '$http','$uibModal', 'commonDialog','record', function ($scope, $http,$uibModal,commonDialog,record) {
$scope.record = record;
$scope.pagination = {};
$scope.params = {record_id:record.id};
$scope.listDetail = function (page) {
var params = angular.copy($scope.params);
params.page = page || $scope.pagination.page || 1;
$http.get('/sys/risk/details',{params:params}).then(function (res) {
$scope.details = res.data.data;
$scope.pagination = res.data.pagination;
})
};
$scope.listDetail(1);
$scope.addRemark = function () {
$uibModal.open({
templateUrl: '/static/risk/templates/risk_remark.html',
controller: 'RiskDetailRemarkCtrl',
resolve:{record_id:function () {
return record.id;
}}
}).result.then(function () {
$scope.listDetail(1);
commonDialog.alert({
title: 'Success',
type: 'success'
});
})
}
$scope.dealDirectly = function () {
commonDialog.confirm({
title: 'Confirm',
content: '确定关结这次预警?'
}).then(function () {
$http.put('/sys/risk/records/'+ record.id+'/directly').then(function () {
commonDialog.alert({
title: 'Success',
type: 'Success'
});
$scope.listDetail(1);
$scope.record.status=1;
}).then(function (resp) {
commonDialog.alert({
title: 'Error',
content: resp.data.message,
type: 'Error'
});
})
})
}
}]);
app.controller('RiskDetailRemarkCtrl', ['$scope', '$http','record_id','commonDialog', function ($scope, $http,record_id,commonDialog) {
$scope.addRemarkParams = {record_id:record_id};
$scope.addRemark = function () {
var params = angular.copy($scope.addRemarkParams);
$http.post('/sys/risk/details/remark',params).then(function (res) {
$scope.$close();
}).then(function (resp) {
commonDialog.alert({
title: 'Error',
content: resp.data.message,
type: 'Error'
});
})
}
}]);
app.controller('RiskRecordHandleCtrl', ['$scope', '$http','record_id','commonDialog', function ($scope, $http,record_id,commonDialog) {
$scope.params= {};
$scope.handle = function () {
$http.put('/sys/risk/records/'+ record_id+'/deal', $scope.params).then(function () {
$scope.$close();
}).then(function (resp) {
commonDialog.alert({
title: 'Error',
content: resp.data.message,
type: 'Error'
});
})
}
}]);
app.filter('risk_type', function () {
return function (riskStr) {
angular.forEach(riskType,function (type) {
riskStr = riskStr.replace(type.code,type.label);
})
return riskStr;
};
});
app.filter('status_type', function () {
return function (riskStr) {
var statusResult = '';
switch (riskStr){
case('0'): statusResult = '待处理';break;
case('1'): statusResult = '已处理';break;
case('2'): statusResult = '处理中';break;
default: statusResult = '';
}
return statusResult;
};
});
return app;
});

@ -0,0 +1,58 @@
<div ui-view>
<section class="content-header">
<h1>Risk Manager</h1>
<ol class="breadcrumb">
<li><i class="fa fa-gift"></i> Risk</li>
<li class="active">Risk Manager</li>
</ol>
</section>
<section class="content">
<div class="box box-default">
<div class="box-header">Records</div>
<div class="box-body table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Create Time</th>
<th>Waring Time</th>
<th>Status</th>
<th>Risk Types</th>
<th>Risk Counts</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td>{{record.client_moniker}}</td>
<td>{{record.create_time}}</td>
<td>{{record.expiry_time}}</td>
<td>{{record.status|status_type}}</td>
<td>{{record.risk_types|risk_type}}</td>
<td>{{record.risk_counts}}</td>
<td>
<a class="text-primary" role="button" title="Detail" ui-sref="analysis_monitoring.risk_orders({'record_id':record.id})">
<i class="fa fa-search" ></i>
</a>
</td>
</tr>
</tbody>
</table>
<div class="modal-footer">
<uib-pagination ng-if="records.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadRecords()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
</div>
</div>
</div>
</section>
</div>

@ -0,0 +1,63 @@
<div ui-view>
<section class="content-header">
<h1>Risk Manager</h1>
<ol class="breadcrumb">
<li><i class="fa fa-gift"></i> Risk</li>
<li class="fa fa-gift">Risk Manager</li>
<li class="active">Handling Detail</li>
</ol>
</section>
<section class="content">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref="analysis_monitoring.risk_orders({'record_id':record.id})">Risk Orders</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_history({'record_id':record.id})">Risk history</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_detail({'record_id':record.id})">Handling Detail</a>
</li>
</ul>
<div class="box box-default">
<div class="box-header">Handling Details</div>
<div class="box-header" ng-if="record.status==0" style="text-align: right;">
<button type="button" class="btn btn-info" ng-click="addRemark()">Handle</button>
<button type="button" class="btn btn-info" ng-click="dealDirectly()">Close Risk</button>
</div>
<div class="box-body table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Handle Time</th>
<th>Operator</th>
<th>Detail</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in details">
<td>{{record.create_time}}</td>
<td>{{record.auditor}}</td>
<td>{{record.remark}}</td>
</tr>
</tbody>
</table>
<div class="modal-footer">
<uib-pagination ng-if="details.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="listDetail()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
</div>
</div>
</div>
</section>
</div>

@ -0,0 +1,32 @@
<section class="content-header">
<h1>Add Remark</h1>
</section>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="box-solid">
<div class="box box-warning">
<div class="box-header">
<form role="form" style="margin:0px auto;width: 50%">
<div class="form-group">
<label>Limit Amount</label>
<input ng-model="params.limitAmount" name="code" class="form-control" type="text"/>
</div>
<div class="form-group">
<label>
<input type="checkbox" ng-model="params.disableMerchat" class="ng-pristine ng-untouched ng-valid">
Disable Merchant
</label>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" ng-click="handle()">commit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,69 @@
<div ui-view>
<section class="content-header">
<h1>Risk Manager</h1>
<ol class="breadcrumb">
<li><i class="fa fa-gift"></i> Risk</li>
<li class="fa fa-gift">Risk Manager</li>
<li class="active">Risk records</li>
</ol>
</section>
<section class="content">
<ul class="nav nav-tabs">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref="analysis_monitoring.risk_orders({'record_id':record.id})">Risk Orders</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_history({'record_id':record.id})">Risk history</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_detail({'record_id':record.id})">Handling Detail</a>
</li>
</ul>
</ul>
<div class="box box-default">
<!--
<div class="box-header">Latest Record</div>
-->
<div class="box-body table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Create Time</th>
<th>Waring Time</th>
<th>Risk Types</th>
<th>Status</th>
<th>Risk Counts</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in histories">
<td>{{record.client_moniker}}</td>
<td>{{record.create_time}}</td>
<td>{{record.expiry_time}}</td>
<td>{{record.status}}</td>
<td>{{record.risk_types|risk_type}}</td>
<td>{{record.risk_counts}}</td>
</tr>
</tbody>
</table>
<div class="modal-footer">
<uib-pagination ng-if="histories.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="listHistory()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
</div>
</div>
</div>
</section>
</div>

@ -0,0 +1,105 @@
<div ui-view>
<section class="content-header">
<h1>Risk Manager</h1>
<ol class="breadcrumb">
<li><i class="fa fa-gift"></i> Risk</li>
<li class="fa fa-gift">Risk Manager</li>
<li class="active">Risk records</li>
</ol>
</section>
<section class="content">
<ul class="nav nav-tabs">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref="analysis_monitoring.risk_orders({'record_id':record.id})">Risk Orders</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_history({'record_id':record.id})">Risk history</a>
</li>
<li ui-sref-active="active">
<a ui-sref="analysis_monitoring.risk_detail({'record_id':record.id})">Handling Detail</a>
</li>
</ul>
</ul>
<div class="box box-default">
<div class="box-header">Reference Orders</div>
<div class="box-body table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Order Id</th>
<th>Amount</th>
<th>Channel</th>
<th>Create Time</th>
<th>Risk Types</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="order in referenceOrders">
<td>{{order.order_id}}</td>
<td>{{order.amount}}</td>
<td>{{order.channel}}</td>
<td>{{order.create_time}}</td>
<td>{{order.risk_types|risk_type}}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="referenceOrders.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadOrders()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
</div>
</div>
<div class="box box-default">
<div class="box-header">Waring Orders History</div>
<div class="box-body table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Order Id</th>
<th>Amount</th>
<th>Channel</th>
<th>Create Time</th>
<th>Risk Types</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="order in historyOrders">
<td>{{order.order_id}}</td>
<td>{{order.amount}}</td>
<td>{{order.channel}}</td>
<td>{{order.create_time}}</td>
<td>{{order.risk_types|risk_type}}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="historyOrders.length"
class="pagination"
total-items="historyPagination.totalCount"
boundary-links="true"
ng-model="historyPagination.page"
items-per-page="historyPagination.limit"
max-size="10"
ng-change="loadHistorysOrders()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
</div>
</div>
</section>
</div>

@ -0,0 +1,25 @@
<section class="content-header">
<h1>Handle Detail</h1>
</section>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="box-solid">
<div class="box box-warning">
<div class="box-header">
<form role="form" style="margin:0px auto;width: 50%">
<div class="form-group">
<label>Detail</label>
<input ng-model="addRemarkParams.remark" name="code" class="form-control" type="text"/>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" ng-click="addRemark()">commit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,83 @@
package au.com.royalpay.payment.manage.task;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Create by yixian at 2018-05-01 17:15
*/
public class FillExcelTask {
private File rpayCat = new File("C:\\Users\\yixian\\develop\\royalpayv2\\manage\\src\\main\\ui\\static\\data\\royalpayindustry.json");
private File wxCat = new File("C:\\Users\\yixian\\develop\\royalpayv2\\manage\\src\\main\\resources\\wx_industry.json");
private Map<String, String> royalCatMap;
private Map<String, String> wxCatMap;
private File excel = new File("C:\\Users\\yixian\\Documents\\bd_merchants.xlsx");
@Before
public void initCategory() throws IOException {
String rpayCatStr = FileUtils.readFileToString(rpayCat, "utf-8");
JSONArray rpayCatJson = JSON.parseArray(rpayCatStr);
List<JSONObject> flatCollect = rpayCatJson.stream().map(item -> (JSONObject) item)
.flatMap(item -> loadChildren(item).stream()).collect(Collectors.toList());
royalCatMap = rpayCatJson.stream().map(item -> (JSONObject) item)
.flatMap(item -> loadChildren(item).stream())
.collect(Collectors.toMap(item -> item.getString("mccCode"), item -> item.getString("label"), (a, b) -> a));
String wxCatStr = FileUtils.readFileToString(wxCat, "utf-8");
JSONObject wxCatJson = JSON.parseObject(wxCatStr);
wxCatMap = wxCatJson.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> (String) entry.getValue()));
}
private List<JSONObject> loadChildren(JSONObject entity) {
if (entity.containsKey("children") && !entity.getJSONArray("children").isEmpty()) {
List<JSONObject> arr = new ArrayList<>(Arrays.asList(entity));
arr.addAll(entity.getJSONArray("children").stream().map(item -> (JSONObject) item).flatMap(item -> loadChildren(item).stream()).collect(Collectors.toList()));
return arr;
}
return Collections.singletonList(entity);
}
@Test
public void replaceCat() throws IOException, InvalidFormatException {
Workbook wb = WorkbookFactory.create(excel);
Sheet sheet = wb.getSheetAt(0);
for (int rn = 1; rn <= sheet.getLastRowNum(); rn++) {
Row row = sheet.getRow(rn);
Cell wxCatCell = row.getCell(2);
Cell rpCatCell = row.getCell(3);
fillCateLabel(wxCatCell, wxCatMap);
fillCateLabel(rpCatCell, royalCatMap);
}
wb.write(new FileOutputStream("C:\\Users\\yixian\\Documents\\bd_merchants_final.xlsx"));
}
private void fillCateLabel(Cell rpCatCell, Map<String, String> royalCatMap) {
if (rpCatCell == null) {
return;
}
if (rpCatCell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
String typeNum = (int) rpCatCell.getNumericCellValue() + "";
if (royalCatMap.get(typeNum) != null) {
rpCatCell.setCellType(Cell.CELL_TYPE_STRING);
rpCatCell.setCellValue(royalCatMap.get(typeNum));
}
}
}
}
Loading…
Cancel
Save