Merge remote-tracking branch 'origin/master'

master
yixian 6 years ago
commit 7f8b16cd29

@ -36,6 +36,10 @@
<groupId>au.com.royalpay.payment</groupId>
<artifactId>jd-core</artifactId>
</dependency>
<dependency>
<groupId>au.com.royalpay.payment</groupId>
<artifactId>rpay-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.stuxuhai</groupId>
<artifactId>jpinyin</artifactId>

@ -1,3 +1,14 @@
CREATE TABLE `sys_rpay_merchant_apply` (
`merchant_app_id` varchar(50) NOT NULL,
`client_id` int(11) NOT NULL,
`merchant_shortname` varchar(20) NOT NULL,
`business_category` varchar(20) NOT NULL,
`sub_merchant_id` varchar(20) DEFAULT NULL,
`create_time` datetime NOT NULL,
`operator` varchar(50) DEFAULT NULL,
PRIMARY KEY (`merchant_app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AVG_ROW_LENGTH=244;
ALTER TABLE `pmt_refunds`
MODIFY COLUMN `refund_id` varchar(50) NOT NULL COMMENT '退款编号' FIRST ;

@ -13,15 +13,18 @@ public class AddressInfo {
public AddressInfo(String address, String suburb, String state, String postCode, String country) {
this.address = address;
this.suburb = suburb;
this.state = state;
if (!postCode.matches("^\\d{4}$")) {
postCode = "9999";
country = "OTH";
state = "OTH";
}
this.postCode = postCode;
if (country != null && country.length() != 3) {
country = "OTH";
state = "OTH";
postCode = "9999";
}
this.postCode = postCode;
this.state = state;
this.country = country;
}

@ -8,6 +8,8 @@ public interface MerchantLocationService {
List<JSONObject> listMerchantsLocations(PartnerQuery query);
void initClientLocations() throws InterruptedException;
JSONObject getMerchantLocationByMoniker(String clientMoniker);
void updateMerchantLocation(JSONObject manager, String clientMoniker, JSONObject geoData);

@ -5,19 +5,44 @@ import au.com.royalpay.payment.manage.dev.core.MerchantLocationService;
import au.com.royalpay.payment.manage.mappers.system.ClientLocationsMapper;
import au.com.royalpay.payment.manage.merchants.beans.PartnerQuery;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import cn.yixblog.platform.http.HttpRequestGenerator;
import cn.yixblog.platform.http.HttpRequestResult;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.netty.util.internal.ConcurrentSet;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.util.UriComponentsBuilder;
import javax.annotation.Resource;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Service
public class MerchantLocationServiceImpl implements MerchantLocationService {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final String GOOGLE_MAPS_API = "https://maps.googleapis.com/maps/api/geocode/json";
private static final String GOOGLE_API_KEY = "AIzaSyDUu6qXRV-j24rSdbPOMfVdTN1-2OfC2o8";
private ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 100, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private Set<Integer> failureSet = new ConcurrentSet<>();
@Resource
private ClientLocationsMapper clientLocationsMapper;
@Resource
private ClientManager clientManager;
@ -28,6 +53,66 @@ public class MerchantLocationServiceImpl implements MerchantLocationService {
return clientLocationsMapper.getAllMerchantsLocations(params);
}
@Resource
private JdbcTemplate jdbcTemplate;
@Override
public void initClientLocations() throws InterruptedException {
List<Map<String, Object>> clients = jdbcTemplate.queryForList("select client_id, CONCAT(IFNULL(address,''),' ',IFNULL(suburb,''),' ',IFNULL(state,''),' ',IFNULL(country,'')) as 'address' from royalpay_production.sys_clients where client_id not in (select client_id from royalpay_production.sys_clients_locations) ");
final int totalLen = clients.size();
logger.info("total length:" + totalLen);
for (int i = 0; i < totalLen; i++) {
Map<String, Object> client = clients.get(i);
final JSONObject clientObj = new JSONObject(client);
final int idx = i;
pool.execute(new Runnable() {
@Override
public void run() {
try {
processClient(clientObj, idx, totalLen);
} catch (URISyntaxException e) {
failureSet.add(clientObj.getIntValue("client_id"));
}
}
});
Thread.sleep(120);
}
pool.shutdown();
pool.awaitTermination(5, TimeUnit.HOURS);
System.err.println("Failed clients:" + StringUtils.join(failureSet, ","));
}
private void processClient(JSONObject client, int idx, int totalLen) throws URISyntaxException {
String url = UriComponentsBuilder.fromHttpUrl(GOOGLE_MAPS_API)
.queryParam("key", GOOGLE_API_KEY)
.queryParam("address", client.get("address")).toUriString();
HttpRequestGenerator gen = new HttpRequestGenerator(url, RequestMethod.GET);
int clientId = client.getIntValue("client_id");
logger.info("start processing index " + idx + "/" + totalLen + ",client_id=" + clientId);
HttpRequestResult result = gen.execute();
if (result.isSuccess()) {
try {
JSONObject address = result.getResponseContentJSONObj();
System.err.println(address);
JSONArray array1 = address.getJSONArray("results");
JSONObject aarray2 = (JSONObject) array1.get(0);
JSONObject location = aarray2.getJSONObject("geometry").getJSONObject("location");
String longitude = location.getString("lng");
String latitude = location.getString("lat");
String sql = "INSERT royalpay_production.sys_clients_locations values(replace(uuid(),'-','')," + clientId + ",'" + client.getString("address") + "','" + latitude + "','" + longitude + "','System Init',now())";
jdbcTemplate.update(sql);
} catch (Exception e) {
logger.error(e.getMessage(), e);
failureSet.add(clientId);
}
} else {
System.err.print(result.getStatusCode());
failureSet.add(clientId);
}
logger.info("finished index " + idx + "/" + totalLen + ",client_id=" + clientId);
}
@Override
public JSONObject getMerchantLocationByMoniker(String clientMoniker) {
return clientLocationsMapper.findTheLocationByMerchantCode(clientMoniker);

@ -22,4 +22,9 @@ public class ClientLocationsController {
public List<JSONObject> getClientsLocations(PartnerQuery query) {
return merchantLocationService.listMerchantsLocations(query);
}
@RequestMapping(value = "/init")
public void initClientLocations() throws InterruptedException {
merchantLocationService.initClientLocations();
}
}

@ -99,4 +99,7 @@ public interface ClientMapper {
List<JSONObject> findByhfPayUrlNotNull();
@AutoSql(type = SqlType.UPDATE)
void updateRpayEnterpriseId(@Param("client_id") int clientId, @Param("rpay_enterprise_id") String rpayEnterpriseId);
}

@ -0,0 +1,26 @@
package au.com.royalpay.payment.manage.mappers.system;
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;
/**
* Created by yangluo on 2017-03-14.
*/
@AutoMapper(tablename = "sys_rpay_merchant_apply",pkName = "merchant_app_id")
public interface SysRpayMerchantApplyMapper {
@AutoSql(type = SqlType.SELECT)
List<JSONObject> listRpayMerchantApplices(@Param("client_id") int client_id, PageBounds pageBounds);
@AutoSql(type = SqlType.INSERT)
void insertRpayMerchantApply(JSONObject params);
@AutoSql(type = SqlType.SELECT)
List<JSONObject> listByShortName(@Param("client_id") int client_id,@Param("merchant_shortname") String shortName);
}

@ -60,6 +60,9 @@ public interface ClientManager {
@Transactional
void updateClientPaymentConfig(JSONObject manager, String clientMoniker, JSONObject subMerchantInfo);
@Transactional
void updateClientRpayPaymentConfig(JSONObject manager, String clientMoniker, JSONObject rpaySubMerchantInfo);
@Transactional
void updateAliSubMerchantId(JSONObject manager, String clientMoniker, JSONObject aliSubMerchantInfo);
@ -222,6 +225,8 @@ public interface ClientManager {
void disableClient(String clientMoniker, JSONObject manager);
void revertClient(String clientMoniker, JSONObject manager);
JSONObject getAuthFiles(JSONObject manager, String clientMoniker);
void uploadAuthFiles(JSONObject manager, String clientMoniker, ClientAuthFilesInfo filesInfo);
@ -296,6 +301,8 @@ public interface ClientManager {
List<JSONObject> listSubMerchantIdApplys(JSONObject manager, String clientMoniker);
List<JSONObject> listRpaySubMerchantIdApplys(JSONObject manager, String clientMoniker);
String subMerchantApplication(String clientMoniker, SubMerchantIdApply subMerchantApply,JSONObject manager);
List<JSONObject> listMerchantIds(String clientMoniker,JSONObject manager);
@ -329,5 +336,7 @@ public interface ClientManager {
void sendHfEmailNotice(JSONObject order);
void subRpayMerchantApplication(String clientMoniker, JSONObject manager);
void updateAllPartnerPassword(String clientMoniker, List<String> emails);
}

@ -1,12 +1,13 @@
package au.com.royalpay.payment.manage.merchants.core.impls;
import au.com.royalpay.payment.channels.rpay.runtime.RpayApi;
import au.com.royalpay.payment.channels.rpay.runtime.beans.SubRpayMerchantInfo;
import au.com.royalpay.payment.channels.wechat.config.WeChatPayConfig;
import au.com.royalpay.payment.channels.wechat.config.WechatPayEnvironment;
import au.com.royalpay.payment.channels.wechat.runtime.MpPaymentApi;
import au.com.royalpay.payment.channels.wechat.runtime.WxPayClient;
import au.com.royalpay.payment.channels.wechat.runtime.beans.SubMerchantInfo;
import au.com.royalpay.payment.core.PaymentChannelApi;
import au.com.royalpay.payment.core.beans.PayChannel;
import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.core.utils.OrderExpiryRuleResolver;
@ -41,6 +42,7 @@ import au.com.royalpay.payment.manage.mappers.system.MailUnsubMapper;
import au.com.royalpay.payment.manage.mappers.system.ManagerMapper;
import au.com.royalpay.payment.manage.mappers.system.OrgMapper;
import au.com.royalpay.payment.manage.mappers.system.PermissionPartnerModuleMapper;
import au.com.royalpay.payment.manage.mappers.system.SysRpayMerchantApplyMapper;
import au.com.royalpay.payment.manage.mappers.system.SysWxMerchantApplyMapper;
import au.com.royalpay.payment.manage.merchants.beans.ActivityPosterBuilder;
import au.com.royalpay.payment.manage.merchants.beans.BankAccountInfo;
@ -155,8 +157,14 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
@ -251,6 +259,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
@Resource
private SysWxMerchantApplyMapper sysWxMerchantApplyMapper;
@Resource
private SysRpayMerchantApplyMapper sysRpayMerchantApplyMapper;
@Resource
private SpringTemplateEngine thymeleaf;
@Resource
private DeviceManager deviceManager;
@ -272,6 +282,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
@Resource
private ClientInfoCacheSupport clientInfoCacheSupport;
@Resource
private RpayApi rpayApi;
@Resource
private SimpleClientApplyService simpleClientApplyService;
@Resource
@ -759,6 +771,40 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
clientInfoCacheSupport.clearClientCache(clientId);
}
@Override
public void updateClientRpayPaymentConfig(JSONObject manager, String clientMoniker, JSONObject rpaySubMerchantInfo) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkOrgPermission(manager, client);
JSONObject update = new JSONObject();
int clientId = client.getIntValue("client_id");
String originSubMerchantId = client.getString("rpay_enterprise_id");
update.put("client_id", clientId);
String subMerchantId = rpaySubMerchantInfo.getString("rpay_enterprise_id");
update.put("rpay_enterprise_id", subMerchantId);
try {
recordSubMerchantLog(client, rpaySubMerchantInfo, 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("rpay_enterprise_id"), originSubMerchantId)) {
update.put("client_id", child.getIntValue("client_id"));
try {
recordSubMerchantLog(child, rpaySubMerchantInfo, manager);
} catch (Exception e) {
logger.error("记录log_client_sub_merchant_id失败", e);
}
clientMapper.update(update);
}
}
clientInfoCacheSupport.clearClientCache(clientId);
}
@Override
public void updateAliSubMerchantId(JSONObject manager, String clientMoniker, JSONObject aliSubMerchantInfo) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
@ -1553,6 +1599,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
checkAddRate(config, "Bestpay", "bestpay_rate_value", org, "min_bestpay_rate");
checkAddRate(config, "jd", "jd_rate_value", org, "min_jd_rate");
checkAddRate(config, "hf", "hf_rate_value", org, "min_hf_rate");
checkAddRate(config, "Rpay", "Rpay_rate_value", org, "min_Rpay_rate");
configNewClientRate(config, clientId, "Wechat", "wechat_rate_value", org, "min_wechat_rate");
configNewClientRate(config, clientId, "Alipay", "alipay_rate_value", org, "min_alipay_rate");
@ -1560,6 +1607,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
configNewClientRate(config, clientId, "Bestpay", "bestpay_rate_value", org, "min_bestpay_rate");
configNewClientRate(config, clientId, "jd", "jd_rate_value", org, "min_jd_rate");
configNewClientRate(config, clientId, "hf", "hf_rate_value", org, "min_hf_rate");
configNewClientRate(config, clientId, "Rpay", "Rpay_rate_value", org, "min_Rpay_rate");
}
@ -2636,6 +2684,13 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
clientModifySupport.processClientModify(new DisableModify(manager, clientMoniker, false));
}
@Override
public void revertClient(String clientMoniker, JSONObject manager) {
JSONObject client = clientDetail(manager, clientMoniker);
Assert.notEmpty(client);
clientModifySupport.processClientModify(new DisableModify(manager, clientMoniker, true));
}
@Override
public void checkTodo(JSONObject manager, List<TodoNotice> notices) {
if (ManagerRole.OPERATOR.hasRole(manager.getIntValue("role"))) {
@ -3500,6 +3555,21 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return null;
}
@Override
public List<JSONObject> listRpaySubMerchantIdApplys(JSONObject manager, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkOrgPermission(manager, client);
List<JSONObject> applices = sysRpayMerchantApplyMapper.listRpayMerchantApplices(client.getInteger("client_id"),
new PageBounds(Order.formString("create_time.desc")));
if (!applices.isEmpty()) {
return applices;
}
return null;
}
@Override
@CacheEvict(value = ":all_sub_merchant_id_applices:", key = "#clientMoniker")
public String subMerchantApplication(String clientMoniker, SubMerchantIdApply subMerchantApply, JSONObject manager) {
@ -3527,6 +3597,40 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return sub_merchant_id;
}
@Override
public void subRpayMerchantApplication(String clientMoniker, JSONObject manager) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkOrgPermission(manager, client);
List<JSONObject> listByshortName = sysRpayMerchantApplyMapper.listByShortName(client.getIntValue("client_id"),client.getString("short_name"));
if (listByshortName.size()>0) {
throw new BadRequestException("请修改【" + clientMoniker + "】的Company shortName信息请避免和Rpay+商务号列表内的Company Short Name重复");
}
SubRpayMerchantInfo subRpayMerchantInfo = JSONObject.toJavaObject(client, SubRpayMerchantInfo.class);
subRpayMerchantInfo.CheckEmpty();
JSONObject rpayMerchantInfo = rpayApi.registerMerchant(client.getIntValue("client_id"), subRpayMerchantInfo);
if (rpayMerchantInfo != null) {
JSONObject merchantApply = new JSONObject();
merchantApply.put("merchant_id", rpayMerchantInfo.getString("rpay_order_id"));
merchantApply.put("client_id", client.getString("client_id"));
merchantApply.put("create_time", new Date());
merchantApply.put("operator", manager.getString("display_name"));
merchantApply.put("sub_merchant_id", rpayMerchantInfo.getString("merchantId"));
merchantApply.put("business_category", client.getString("royalpayindustry"));
merchantApply.put("merchant_shortname", client.getString("short_name"));
sysRpayMerchantApplyMapper.insertRpayMerchantApply(merchantApply);
clientMapper.updateRpayEnterpriseId(client.getIntValue("client_id"), rpayMerchantInfo.getString("merchantId"));
}else {
throw new BadRequestException("请求失败");
}
}
@Override
public List<JSONObject> listMerchantIds(String clientMoniker, JSONObject manager) {
JSONObject client = getClientInfoByMoniker(clientMoniker);

@ -1,7 +1,13 @@
package au.com.royalpay.payment.manage.merchants.web;
import au.com.royalpay.payment.manage.dev.core.MerchantLocationService;
import au.com.royalpay.payment.manage.merchants.beans.*;
import au.com.royalpay.payment.manage.merchants.beans.BankAccountInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientRateConfig;
import au.com.royalpay.payment.manage.merchants.beans.ClientRegisterInfo;
import au.com.royalpay.payment.manage.merchants.beans.NewAccountBean;
import au.com.royalpay.payment.manage.merchants.beans.PartnerQuery;
import au.com.royalpay.payment.manage.merchants.beans.SubMerchantIdApply;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.permission.manager.RequireManager;
@ -11,17 +17,26 @@ import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.http.HttpUtils;
import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import com.alibaba.fastjson.JSONObject;
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.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
/**
* Created by yixian on 2016-06-27.
*/
@ -66,6 +81,11 @@ public class PartnerManageController {
clientManager.disableClient(clientMoniker, manager);
}
@ManagerMapping(value = "/{clientMoniker}/revert", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public void revertClient(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.revertClient(clientMoniker, manager);
}
@ManagerMapping(value = "/{clientMoniker}/qrcode", method = RequestMethod.GET)
public JSONObject getQrCodeImg(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, QRCodeConfig config) {
return clientManager.getQRCode(manager, clientMoniker, config);
@ -154,6 +174,12 @@ public class PartnerManageController {
public void updatePartnerPaymentConfig(@PathVariable String clientMoniker, @RequestBody JSONObject subMerchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.updateClientPaymentConfig(manager, clientMoniker, subMerchantInfo);
}
@ManagerMapping(value = "/{clientMoniker}/rpay_payment_config", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void updatePartnerRpayPaymentConfig(@PathVariable String clientMoniker, @RequestBody JSONObject rpaySubMerchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.updateClientRpayPaymentConfig(manager, clientMoniker, rpaySubMerchantInfo);
}
@ManagerMapping(value = "/{clientMoniker}/ali_sub_merchant_id", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR})
public void updateAliSubMerchantId(@PathVariable String clientMoniker, @RequestBody JSONObject aliSubMerchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.updateAliSubMerchantId(manager, clientMoniker, aliSubMerchantInfo);
@ -517,7 +543,12 @@ public class PartnerManageController {
return clientManager.listSubMerchantIdApplys(manager,clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/sub_apply",method = RequestMethod.POST,role = {ManagerRole.OPERATOR,ManagerRole.ADMIN})
@ManagerMapping(value = "/{clientMoniker}/list_rpay_sub_applices", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN})
public List<JSONObject> listRpaySubMerchantIdApplys(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.listRpaySubMerchantIdApplys(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/sub_apply", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN})
public String subMerchantApplication(@PathVariable String clientMoniker, @RequestBody SubMerchantIdApply subMerchantIdApply, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.subMerchantApplication(clientMoniker,subMerchantIdApply,manager);
}
@ -550,5 +581,9 @@ public class PartnerManageController {
public void switchHfEmailNotice(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.switchPermission(manager, clientMoniker, "enable_hf_email_notice", pass.getBooleanValue("allow"));
}
@ManagerMapping(value = "/{clientMoniker}/registRpaySubMerchantId", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN})
public void subRpayMerchantApplication(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.subRpayMerchantApplication(clientMoniker, manager);
}
}

@ -0,0 +1,35 @@
package au.com.royalpay.payment.manage.task;
import au.com.royalpay.payment.manage.dev.core.MerchantLocationService;
import au.com.royalpay.payment.tools.scheduler.SynchronizedScheduler;
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 javax.annotation.Resource;
/**
* Created by wangning on 2018/1/2.
*/
@Component
@ConditionalOnProperty(value = "app.run-tasks", havingValue = "true")
public class initClientLocationTask {
@Resource
private MerchantLocationService merchantLocationService;
@Resource
private SynchronizedScheduler synchronizedScheduler;
@Scheduled(cron = "0 0 5 * * *")
public void checkBillOrderCheck() {
synchronizedScheduler.executeProcess("manage_task:initClientLocation", 120_000, () -> {
try {
merchantLocationService.initClientLocations();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}

@ -0,0 +1,3 @@
app.rpay.privateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKikZJwvKZ3dj5QsRy6xN/cPinAZa3leg8X40YzGrMEYWc2nmZY/EczYPq/kUp1uL2uikweDO35fuVpA4rALmJwXhHzsZyhVk4lEjHaqH8rNpVpmrwKP9rMmbFD23Mfvvt+BkKWan2T2dAMbSdjPY0+DTS4sN1ZrqzycRFxKFpohAgMBAAECgYBoO0Mb7WJxehFV6ZANYedPQkG0S2HL4AjeAY2yztDTf/NxUpdw74ZW74i/OgV93C5e/lqVmBzbXNq418XEPUaSohOqbcv+QRlEdlTAtn82aAUp/c9oSogPiHWs2VKiGoutejwVXQ6V9BAGMMegLwVphUu9dgrPC4dnfGO11fvLiQJBANt0VPmdqdG52rNVllKhF5+d+dIamOOQewWZf7HnkW0uYt9kWSbZCYyey4nP7NlONL7NEdUxn9exg/DYzegB99sCQQDEudve+jV2Ay6gbOS+ylHoCxSroF6jlkBQ0q7LIsWAAzIVLOuo5skC+wJmHzKXDoQBLXcFerP/T/iUSzisKqSzAkEAmjRVXY02/gLttWQnm+pMckGMgOFlm0oz18xzmSwR2TlmCnk12AFcH26ZsT3kvRGiKIxqwnb7TZIUF1IQ5b00TwJALD7xKNF1vLkyf3p+aDrw+ROk7oT/RCPDC2qXTbDgYs5VMVYNGsvtYfI6s+VIZ5koL2ueXWkfmsjNy+yvLmnY6QJADV9xlAa1+mWN2TfzAugd3L0fNLqPJPHBKQS5/bBKcoZlwfXwByrcCceKaCntJRZ056eQ7IeqkJfxjkEo/kgaRg==
app.rpay.rpayPublicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxRx80vX64kSu5nrHbwPX/3SctyFIGrjBEJ9NEBOQPP4KHRQ49QyhVZ1fu7NvtD98n+PGR0ULUrK6S4KsYw6Huaga2RwbSVVkYPFGEFZ70XvjlGSzBG7fkbU8nscWAPOP+k5STD5sOZ35+9ko2H7IBz5RAclREoyB4/JaorQiBrEqS8RmX2TCjtx2lgi9TTcLinMDmULcg5qz44xpn08RwjuVpwRXyWFraxSaF0AcnpqstHON9AEyYanBjpQzR7yvj1IUGPMVNKpu/f4Z0ABvGZ9iAe3lyYESkkZ93ajy4vylY3YQvQsgHAsgazVsg2b25TC6TvAp9xPcaO0U8aoLLQIDAQAB
app.rpay.appId=8850afd2-6183-4cff-83af-9be5ca916e16

@ -1,6 +1,6 @@
server.port=5000
spring.profiles.active=dev,alipay,bestpay,jd,wechat
spring.profiles.active=dev,alipay,bestpay,jd,wechat,rpay
env.company=RoyalPay

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

@ -763,6 +763,19 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
})
})
};
$scope.revertClient = function () {
commonDialog.confirm({
title: 'Revert Partner',
content: 'Are you sure to Revert ' + $scope.partner.company_name + '?'
}).then(function () {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/revert').then(function () {
$state.go('^');
commonDialog.alert({title: 'Revert', content: 'Partner Already Revert', type: 'success'});
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.commitToCompliance = function () {
commonDialog.confirm({
@ -1888,6 +1901,7 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.rate.bestpay_rate_value = parseFloat($scope.sysRateConfig.t1.Bestpay);
$scope.rate.jd_rate_value = parseFloat($scope.sysRateConfig.t1.JDpay);
$scope.rate.hf_rate_value = parseFloat($scope.sysRateConfig.t1.HFpay);
$scope.rate.Rpay_rate_value = parseFloat($scope.sysRateConfig.t1.Rpay);
break;
}
case '2': {
@ -1897,6 +1911,7 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.rate.alipayonline_rate_value = parseFloat($scope.sysRateConfig.t2.AlipayOnline);
$scope.rate.jd_rate_value = parseFloat($scope.sysRateConfig.t2.JDpay);
$scope.rate.hf_rate_value = parseFloat($scope.sysRateConfig.t2.HFpay);
$scope.rate.Rpay_rate_value = parseFloat($scope.sysRateConfig.t2.Rpay);
break;
}
case '3': {
@ -1906,6 +1921,7 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.rate.alipayonline_rate_value = parseFloat($scope.sysRateConfig.t3.AlipayOnline);
$scope.rate.jd_rate_value = parseFloat($scope.sysRateConfig.t3.JDpay);
$scope.rate.hf_rate_value = parseFloat($scope.sysRateConfig.t3.HFpay);
$scope.rate.Rpay_rate_value = parseFloat($scope.sysRateConfig.t3.Rpay);
break;
}
}
@ -3081,6 +3097,9 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/list_sub_applices', {params: {}}).then(function (resp) {
$scope.subMerchantInfos = resp.data;
});
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/list_rpay_sub_applices', {params: {}}).then(function (resp) {
$scope.subRpayMerchantInfos = resp.data;
});
};
$scope.useSubMerchantId = function (sub_merchant_id) {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/payment_config', {sub_merchant_id: sub_merchant_id}).then(function (resp) {
@ -3094,10 +3113,22 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'})
});
}
$scope.applySubMerchantId = function () {
$scope.useRpaySubMerchantId = function (sub_merchant_id) {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/rpay_payment_config', {rpay_enterprise_id: sub_merchant_id}).then(function (resp) {
commonDialog.alert({
title: 'Success',
content: 'Modify Rpay+ Sub Merchant ID successfully',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'})
});
}
$scope.applyWxSubMerchantId = function () {
$uibModal.open({
templateUrl: '/static/payment/partner/templates/apply_sub_merchant_id.html',
controller: 'applySubMerchantIdCtrl',
templateUrl: '/static/payment/partner/templates/apply_wx_sub_merchant_id.html',
controller: 'applyWxSubMerchantIdCtrl',
resolve: {
subMerchantInfo: function () {
return $scope.partner;
@ -3109,10 +3140,26 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}).result.then(function () {
$scope.loadSubMerchantInfos();
})
};
$scope.applyRpaySubMerchantId = function () {
$http.post('/sys/partners/' + $scope.partner.client_moniker + '/registRpaySubMerchantId').then(function (resp) {
commonDialog.alert({
title: 'Success',
content: 'Modify Rpay+ Sub Merchant ID successfully',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'})
});
};
$scope.loadSubMerchantInfos();
}]);
app.controller('applySubMerchantIdCtrl', ['$scope', '$http', '$uibModal', '$state', 'subMerchantInfo', '$filter', 'merchantIds', 'commonDialog', function ($scope, $http, $uibModal, $state, subMerchantInfo, $filter, merchantIds, commonDialog) {
app.controller('applyWxSubMerchantIdCtrl', ['$scope', '$http', '$uibModal', '$state', 'subMerchantInfo', '$filter', 'merchantIds', 'commonDialog', function ($scope, $http, $uibModal, $state, subMerchantInfo, $filter, merchantIds, commonDialog) {
$scope.wxIndustries = angular.copy(wxMerchantIndustries);
$scope.subMerchantInfo = angular.copy(subMerchantInfo);
$scope.merchantIds = merchantIds.data;

@ -171,6 +171,7 @@
<li role="presentation" ng-class="{active:bankCtrl.rate_name=='Bestpay'}"><a role="button" ng-click="bankCtrl.rate_name='Bestpay'">Bestpay</a></li>
<li role="presentation" ng-class="{active:bankCtrl.rate_name=='jd'}"><a role="button" ng-click="bankCtrl.rate_name='jd'">JDpay</a></li>
<li role="presentation" ng-class="{active:bankCtrl.rate_name=='hf'}"><a role="button" ng-click="bankCtrl.rate_name='hf'">HFpay</a></li>
<li role="presentation" ng-class="{active:bankCtrl.rate_name=='Rpay'}"><a role="button" ng-click="bankCtrl.rate_name='Rpay'">Rpay+</a></li>
</ul>
<div class="table-responsive">
<table class="table table-bordered">
@ -206,6 +207,7 @@
<div style="text-align: center">
<a role="button" style="margin-bottom: 25px;" class="btn btn-success btn-sm ng-scope" ng-if="('10'|withRole)" ng-click="complianceCheck()">check</a>
</div>
</div>
</div>
</div>

@ -78,6 +78,7 @@
</b>
<span ng-if="partner.is_valid==0" ng-class="{pass_timeout:partner.is_valid==0}">(已禁用)</span>
</h3>
<button ng-if="!partner.is_valid" type="button" class="btn btn-success" style="float:right;" ng-click="revertClient()">Revert</button>
</div>
<div class="box-body" ng-if="partner.is_valid==1">
<div ng-if="partner.open_status != 5 && partner.open_status!=10">
@ -255,7 +256,7 @@
<a ui-sref=".product">Product</a>
</li>
<li ui-sref-active="active" ng-if="('10'|withRole) && partner.is_valid==1">
<a ui-sref=".sub_merchant_applicaitons">Wechat Merchant Id Applicaitons</a>
<a ui-sref=".sub_merchant_applicaitons">Merchant Id Applicaitons</a>
</li>
<li ui-sref-active="active" ng-if="partner.is_valid==1">
<a ui-sref=".permission_client">Permissions</a>

@ -141,7 +141,7 @@
<label class="control-label col-sm-4" for="hf_rate_value_input">HF Rate Value</label>
<div class="col-sm-6">
<div class="input-group">
<input type="number" name="jd_rate_value" stringToNumber2 class="form-control" ng-model="rate.hf_rate_value"
<input type="number" name="hf_rate_value" stringToNumber2 class="form-control" ng-model="rate.hf_rate_value"
min="0.6" max="2.2" step="0.1" id="hf_rate_value_input" required>
<div class="input-group-addon">%</div>
</div>
@ -160,6 +160,30 @@
</div>
</div>
<div class="form-group"
ng-class="{'has-error':rate_form.Rpay_rate_value.$invalid && rate_form.Rpay_rate_value.$dirty}">
<label class="control-label col-sm-4" for="Rpay_rate_value_input">Rpay+ Rate Value</label>
<div class="col-sm-6">
<div class="input-group">
<input type="number" name="Rpay_rate_value" stringToNumber2 class="form-control" ng-model="rate.Rpay_rate_value"
min="0.6" max="2.2" step="0.1" id="Rpay_rate_value_input" required>
<div class="input-group-addon">%</div>
</div>
<div ng-messages="rate_form.Rpay_rate_value.$error" ng-if="rate_form.Rpay_rate_value.$dirty">
<div class="small text-danger" ng-message="max">
<i class="glyphicon glyphicon-alert"></i> No more than 2.2%
</div>
<div class="small text-danger" ng-message="min">
<i class="glyphicon glyphicon-alert"></i> No less than 0.6%
</div>
<div class="small text-danger" ng-message="required">
<i class="glyphicon glyphicon-alert"></i> Required Field
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" for="active_time_input">Active Date</label>
<div class="col-sm-6">

@ -48,6 +48,14 @@
</p>
</div>
</div>
<div class="form-group" ng-if="'10'|withRole">
<label class="col-sm-3 control-label">Rpay+ Institution Merchant Id</label>
<div class="col-sm-9">
<p class="form-control-static">
{{paymentInfo.rpay_enterprise_id||'初始化'}}
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Ali Sub Merchant Id</label>

@ -31,11 +31,11 @@
<div class="box box-warning">
<div class="box-header">
<h3 class="box-title pull-left" ng-if="partner.sub_merchant_id">
Sub Merchant Id : {{partner.sub_merchant_id}}
Wechat Sub Merchant Id : {{partner.sub_merchant_id}}
<i class="fa fa-clock-o text-danger" title="Using temp Sub Merchant ID" ng-if="partner.temp_sub_merchant"></i>
</h3>
<button role="button" class="btn btn-info pull-right" title="Apply Sub Merchant Id"
ng-click="applySubMerchantId()">
ng-click="applyWxSubMerchantId()">
<i class="fa fa-plus"></i>
Apply Sub Merchant Id
</button>
@ -88,4 +88,65 @@
</div>
</div>
</div>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="box-solid">
<div class="box box-warning">
<div class="box-header">
<h3 class="box-title pull-left">
Rpay+ Sub Merchant Id : {{partner.rpay_enterprise_id}}
<i class="fa fa-clock-o text-danger" title="Using temp Sub Merchant ID" ng-if="partner.temp_sub_merchant"></i>
</h3>
<button role="button" class="btn btn-info pull-right" title="Apply Sub Merchant Id"
ng-click="applyRpaySubMerchantId()">
<i class="fa fa-plus"></i>
Apply Sub Merchant Id
</button>
</div>
</div>
<div class="box">
<div class="box-header">
<h3 class="box-title">List of Sub Merchant Id</h3>
</div>
<div class="box-body col-sm-6" ng-repeat="id_apply in subRpayMerchantInfos">
<ul class="list-group ui_desk">
<li class="list-group-item list-group-item-success">
<b>Sub Merchant Id</b>
<b style="float: right"><span
ng-if="partner.rpay_enterprise_id == id_apply.sub_merchant_id"><small
class="text-red">(当前使用)</small></span>{{id_apply.sub_merchant_id}}</b>
</li>
<li class="list-group-item list-group-item-success">
Apply Time
<span style="float: right" ng-bind="id_apply.create_time"></span>
</li>
<li class="list-group-item list-group-item-success">
Company Short Name
<span style="float:right;">{{id_apply.merchant_shortname | cut:true:20:' ...'}}</span>
</li>
<li class="list-group-item list-group-item-success">
Business Category
<span style="float: right">{{id_apply.business_category | partner_royalpay_industry}}</span>
</li>
<li class="list-group-item list-group-item-success">
Operator
<span style="float: right" ng-bind="id_apply.operator"></span>
</li>
</ul>
<div class="box_desk">
<div class="content_button">
<button role="button" class="btn btn-info" title="use"
ng-click="useRpaySubMerchantId(id_apply.sub_merchant_id)">
USE
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -433,6 +433,9 @@ input.value:focus {
.keyboard-grids .key.paynow.alipay {
background: #108ee9;
}
.keyboard-grids .key.paynow.rpay {
background: #FF2D55;
}
.alipay {
color: #108ee9;
@ -442,6 +445,10 @@ input.value:focus {
color: #09bb07;
}
.rpay {
color: #FF2D55;
}
.keyboard-grids .key.paynow > .label {
display: block;
position: absolute;

@ -366,6 +366,10 @@ input.value:focus {
background-color: #108ee9;
}
.button_sp_area.alipay .paynow {
background-color: #FF2D55;
}
.button_sp_area .remark-btn {
width: 35%;
background: #20C1ED

@ -431,6 +431,9 @@ input.value:focus {
.keyboard-grids .key.paynow.alipay {
background: #108ee9;
}
.keyboard-grids .key.paynow.rpay {
background: #FF2D55;
}
.alipay {
color: #108ee9;

@ -0,0 +1,79 @@
/**
* Created by yixian on 2016-07-15.
*/
$(document).ready(function () {
'use strict';
decode();
function decode() {
var redirect = window.redirect;
while(redirect.indexOf('://')<0){
redirect = decodeURIComponent(redirect);
if(redirect==window.redirect){
break;
}
window.redirect = redirect;
}
}
var dataCache = {paying: false};
$('#key_P').bind('touchstart', startPay);
function startPay() {
$('#wdiv').show();
if (dataCache.paying) {
return;
}
dataCache.paying = true;
$.ajax({
url: '/api/v1.0/alipay/partners/' + window.client_moniker + '/orders/'+window.order_id+'/order_params',
method: 'GET',
dataType: 'json',
success: function (pay) {
if (pay.direct_paid) {
location.href = window.redirect;
return;
}
if (window.AlipayJSBridge) {
callPayment();
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', callPayment, false);
}
function callPayment() {
try {
AlipayJSBridge.call('tradePay', {
tradeNO: pay.trade_no
}, function (res) {
dataCache.paying = false;
if (res.resultCode == '9000') {
AlipayJSBridge.call('startApp', {
appId: '20000056',
param: {
actionType: 'showSuccPage',
payResult: res.result
},
closeCurrentApp: false
});
location.href = window.redirect;
} else {
alert(res.memo);
}
$('#wdiv').hide();
})
} catch (err) {
alert(err);
$('#wdiv').hide();
}
}
},
error: function (jqXhr) {
alert(jqXhr.responseJSON.message);
$('#wdiv').hide();
dataCache.paying = false;
}
})
}
});

@ -0,0 +1,139 @@
/**
* Created by yixian on 2016-07-15.
*/
$(document).ready(function () {
'use strict';
decode();
function decode() {
if (window.client_moniker == 'PINE') {
alert('debug:origin redirect:' + window.redirect);
}
var redirect = window.redirect;
while (redirect.indexOf('://') < 0) {
redirect = decodeURIComponent(redirect);
if (redirect == window.redirect) {
break;
}
window.redirect = redirect;
}
}
var dataCache = {paying: false};
$('#key_P').bind('touchstart', startPay);
if (window.tradeNo) {
if (window.AlipayJSBridge) {
callPayment(window.tradeNo);
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', function () {
callPayment(window.tradeNo);
}, false);
}
}
function startPay() {
$('#wdiv').show();
if (dataCache.paying) {
return;
}
dataCache.paying = true;
$.ajax({
url: './preorder',
method: 'GET',
dataType: 'json',
success: function (pay) {
if (pay.direct_paid) {
location.href = window.redirect + (window.redirect.indexOf('?') < 0 ? '?' : '&') + 'success=true';
return;
}
if (window.AlipayJSBridge) {
callPayment(pay.trade_no);
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', function () {
callPayment(pay.trade_no);
}, false);
}
},
error: function (jqXhr) {
alert(jqXhr.responseJSON.message);
$('#wdiv').hide();
dataCache.paying = false;
}
})
}
function callPayment(tradeNo) {
try {
if (window.client_moniker == 'PINE') {
alert('debug:trade no=' + tradeNo)
}
AlipayJSBridge.call('tradePay', {
tradeNO: tradeNo
}, function (res) {
dataCache.paying = false;
if (res.resultCode == '9000') {
AlipayJSBridge.call('startApp', {
appId: '20000056',
param: {
actionType: 'showSuccPage',
payResult: res.result
},
closeCurrentApp: false
});
startCheckOrder(window.client_moniker, window.merchant_orderid);
} else {
alert(res.memo);
if (window.tradeNo) {
location.href = window.redirect + (window.redirect.indexOf('?') < 0 ? '?' : '&') + 'success=false';
}
}
$('#wdiv').hide();
})
} catch (err) {
alert(err);
$('#wdiv').hide();
}
}
function startCheckOrder(clientMoniker, merchantOrderId) {
function checkOrderStd() {
$.ajax({
url: '/api/v1.0/payment/clients/' + clientMoniker + '/orders/' + merchantOrderId + '/status',
method: 'GET',
dataType: 'json',
success: function (res) {
if (res.paid) {
location.href = window.redirect + (window.redirect.indexOf('?') < 0 ? '?' : '&') + 'success=true';
} else {
setTimeout(checkOrderStd, 500);
}
}
})
}
checkOrderStd();
}
function waitForPaymentSuccess(orderId) {
var sock = new SockJS('/register');
var client = Stomp.over(sock);
client.connect({}, function () {
client.subscribe('/app/payment/orders/' + orderId, function (msg) {
var json = JSON.parse(msg.body);
var concat = '?';
if (window.redirect.indexOf('?') > 0) {
concat = '&';
}
location.href = window.redirect + concat + 'time=' + json.time + '&nonce_str=' + json.nonce_str + '&sign=' + json.sign + '&success=true';
})
})
}
});

@ -0,0 +1,473 @@
/**
* Created by yixian on 2017-05-08
*/
$(function () {
'use strict';
document.querySelector('body').addEventListener('touchmove', function (e) {
if (!document.querySelector('.coupons').contains(e.target)) {
e.preventDefault();
}
})
var dataCache = {price: '0', coupons: [], coupon_groups: {}};
var exchangeRate = parseFloat(window.exchange_rate);
if (window.AlipayJSBridge) {
AlipayJSBridge.call('hideOptionMenu');
} else {
document.addEventListener('AlipayJSBridgeReady', function () {
AlipayJSBridge.call('hideOptionMenu');
}, false);
}
dataCache.paying = false;
var ctrl = {};
$('.ff.key').bind('touchstart', function () {
if (dataCache.paying) {
return;
}
var char = $(this).attr('data-char');
appendChar(char);
});
$('.coupons .use-check').click(function () {
if ($(this).hasClass('disabled')) {
return;
}
var couponId = $(this).attr('data-coupon-id');
var couponGroup = $(this).attr('data-coupon-group');
if (couponGroup) {
var prevCouponId = dataCache.coupon_groups[couponGroup];
if (prevCouponId) {
var prevIdx = dataCache.coupons.indexOf(prevCouponId);
if (prevIdx >= 0) {
dataCache.coupons.splice(prevIdx, 1);
}
if (prevCouponId != couponId) {
$('.coupons .use-check[data-coupon-id="' + prevCouponId + '"]').removeClass('checked').addClass('unchecked');
dataCache.coupon_groups[couponGroup] = couponId;
} else {
dataCache.coupon_groups[couponGroup] = null;
}
} else {
dataCache.coupon_groups[couponGroup] = couponId;
}
}
if ($(this).is('.checked')) {
$(this).removeClass('checked').addClass('unchecked');
} else {
$(this).removeClass('unchecked').addClass('checked');
}
var checked = $(this).is('.checked');
if (checked) {
dataCache.coupons.push(couponId);
updatePrice();
} else {
var idx = dataCache.coupons.indexOf(couponId);
dataCache.coupons.splice(idx, 1);
}
});
$('#key_B').bind('touchstart', function () {
backspace();
});
function updatePoundage(price) {
if (window.extensions.indexOf('customerrate') >= 0 && window.rateValue != null) {
if (window.use_customised_rate) {
var rate = new Decimal(100).plus(window.rateValue).div(100);
var poundageValue = new Decimal(dataCache.price).mul(rate).sub(dataCache.price);
} else {
var rateRemain = new Decimal(100).sub(window.rateValue).div(100);
poundageValue = new Decimal(dataCache.price).div(rateRemain).sub(dataCache.price);
}
dataCache.poundageValue = poundageValue.toFixed(2, Decimal.ROUND_HALF_UP);
return poundageValue.plus(price).toFixed(2, Decimal.ROUND_HALF_UP);
}
return price;
}
function updatePrice() {
$('#audVal').html(dataCache.price);
var realPrice = dataCache.price;
$('#audValReal').html(realPrice);
var surchargeData = calculateSurcharge(realPrice);
var price = surchargeData.newPrice || realPrice;
var priceBeforeDiscount = price;
dataCache.discounts = [];
dataCache.tax = surchargeData.tax;
dataCache.surcharge = surchargeData.surcharge;
$(window.coupons).each(function () {
price = this.handleDiscount(price, dataCache.price, dataCache.discounts, dataCache.coupons);
});
dataCache.customSurcharge = new Decimal(price).sub(realPrice).toFixed(2,Decimal.ROUND_HALF_UP);
dataCache.finalPrice = new Decimal(price).toFixed(2, Decimal.ROUND_FLOOR);
var rate = 'CNY' == window.currency ? 1 : exchangeRate;
var cnyVal = Decimal.mul(price, rate).toFixed(2, Decimal.ROUND_HALF_UP);
$('#cnyVal').html(cnyVal);
dataCache.currencyPrice = 'CNY' == window.currency ? Decimal.div(priceBeforeDiscount, exchangeRate).toFixed(2, Decimal.ROUND_FLOOR) : priceBeforeDiscount;
}
function updatePoundageStatus() {
$(window.coupons).each(function () {
var coupon = this;
var couponId = coupon.couponId();
if (coupon.isEnable(dataCache.currencyPrice || 0)) {
$('.coupons .use-check[data-coupon-id=' + couponId + ']').removeClass('disabled');
} else {
var dom = $('.coupons .use-check[data-coupon-id=' + couponId + ']').addClass('disabled');
var couponGroup = dom.attr('data-coupon-group');
if (couponGroup) {
if (dataCache.coupon_groups[couponGroup] == couponId) {
dataCache.coupon_groups[couponGroup] = null;
}
}
var idx = dataCache.coupons.indexOf(couponId);
if (idx >= 0) {
dataCache.coupons.splice(idx, 1);
}
dom.removeClass('checked').addClass('unchecked');
}
})
}
updatePoundageStatus();
function backspace() {
dataCache.price = dataCache.price.substring(0, dataCache.price.length - 1);
if (dataCache.price.length == 0) {
dataCache.price = '0';
}
updatePrice();
updatePoundageStatus();
}
function appendChar(char) {
var pointLocation = dataCache.price.indexOf('.');
if (pointLocation >= 0 || char == '.' || dataCache.price.length < 5) {
if (pointLocation >= 0 && char == '.') {
return;
}
if (pointLocation >= 0 && pointLocation <= dataCache.price.length - 3) {
return;
}
if (dataCache.price == '0' && char != '.') {
dataCache.price = '';
}
dataCache.price += char;
updatePrice();
updatePoundageStatus();
}
}
$('#coupon-box-toggle').click(function () {
$('.coupons-container').addClass('show');
});
$('.coupons-container>.coupons-mask,.coupons-container #close-coupon-box').click(function () {
$(this).parents('.coupons-container').removeClass('show');
});
$('.remark-btn').click(function () {
var cfg = {
title: '备注 Remark',
template: '',
initialize: function (dialog) {
$('<textarea rows="2" autofocus="autofocus"></textarea>').addClass('remark-input').attr('name', 'remark').val(dataCache.remark || '').appendTo($('.weui_dialog_bd', dialog));
},
confirm: function (dialog, chosen) {
if (chosen) {
var remark = $('textarea[name="remark"]', dialog).val();
if (remark) {
$('#remark-box').text('备注:' + remark).show()
} else {
$('#remark-box').text('').hide();
}
dataCache.remark = remark;
}
}
};
showWeuiDialog(cfg);
});
$('.paydetail').click(function () {
var config = {
title: 'Payment Detail',
template: '',
initialize: function (dialog) {
var bd = $('.weui_dialog_bd', dialog);
var currencySymbol = window.currency == 'AUD' ? '$' : '¥';
$('<p></p>').html('Input Price 输入金额:' + currencySymbol + dataCache.price).appendTo(bd);
if (parseFloat(dataCache.customSurcharge) > 0) {
$('<p></p>').html('Surcharge 手续费(' + window.rateValue + '%):+' + currencySymbol + dataCache.customSurcharge).appendTo(bd);
}
$(dataCache.discounts).each(function () {
$('<p></p>').html(this.title + ':-' + currencySymbol + this.amount).appendTo(bd);
});
$('<p></p>').addClass('final').html('Final 支付金额:' + currencySymbol + (dataCache.finalPrice || 0)).appendTo(bd);
}
};
showWeuiDialog(config);
});
$('#key_P').click(function () {
if (window.requireRemark) {
if (!dataCache.remark) {
var config = {
title: '请先输入备注',
template: ''
};
showWeuiDialog(config);
}
}
});
$('#key_P').bind('touchstart', function () {
if (window.requireRemark) {
if (!dataCache.remark) {
return;
}
}
$('#key_P').addClass('hidden');
$('#key_Loading').removeClass('hidden');
if (dataCache.paying) {
return;
}
dataCache.paying = true;
var data = {price: dataCache.price + '', original_number: true, currency: window.currency};
if (dataCache.remark) {
data.description = dataCache.remark;
}
if (window.extensions.indexOf('preauthorize') >= 0) {
data.preauthorize = true;
}
if (window.extensions.indexOf('qrcodemode') >= 0) {
data.qrmode = true;
}
if (window.extensions.indexOf('customerrate') >= 0) {
data.customerrate = true;
}
data.coupons = dataCache.coupons;
data.customerId = window.RpayUserId;
data.qrcodeVersion = window.qrcodeVersion;
dataCache.remark = '';
window.RPayPlus.send("showLoading", null, null);
$.ajax({
url: '/api/v1.0/rpay/partners/' + window.client_moniker + '/orders',
method: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
dataType: 'json',
success: function (resp) {
window.RPayPlus.send("closeLoading", null, null);
pay(resp,function(data){
if(data == 'success'){
location.href = '/api/v1.0/rpay/partners/' + window.client_moniker + '/orders/' + resp.mch_order_id + '/result'
}else if(data == 'fail'){
alert('Oops,Network fluctuation,please try again later...');
}
$('#key_P').removeClass('hidden');
$('#key_Loading').addClass('hidden');
dataCache.paying = false;
});
// if (window.AlipayJSBridge) {
// callPayment();
// } else {
// // 如果没有注入则监听注入的事件
// document.addEventListener('AlipayJSBridgeReady', callPayment, false);
// }
//
// function callPayment() {
// try {
// AlipayJSBridge.call('tradePay', {
// tradeNO: pay.trade_no
// }, function (res) {
// dataCache.paying = false;
// if (res.resultCode == '9000') {
// AlipayJSBridge.call('startApp', {
// appId: '20000056',
// param: {
// actionType: 'showSuccPage',
// payResult: res.result
// },
// closeCurrentApp: false
// });
// startCheckOrder(pay.order_id, '/api/v1.0/alipay/partners/' + window.client_moniker + '/orders/' + pay.order_id + '/result');
// } else if (res.resultCode == '6001') {
// //do nothing
// } else {
// if (res.memo) {
// weuiAlert(res.memo);
// }
// }
// $('#key_P').removeClass('hidden');
// $('#key_Loading').addClass('hidden');
// })
// } catch (err) {
// weuiAlert(err)
// }
// }
},
error: function (jqXhr) {
window.RPayPlus.send("closeLoading", null, null);
weuiAlert(jqXhr.responseJSON.message);
dataCache.paying = false;
$('#key_P').removeClass('hidden');
$('#key_Loading').addClass('hidden');
}
})
});
function startCheckOrder(orderId, url) {
function checkOrderStd() {
$.ajax({
url: '/api/v1.0/payment/orders/' + orderId + '/status',
method: 'GET',
dataType: 'json',
success: function (res) {
if (res.paid) {
location.href = url;
} else {
setTimeout(checkOrderStd, 500);
}
}
})
}
checkOrderStd();
}
function weuiAlert(msg) {
var config = {
template: msg
};
showWeuiDialog(config);
}
function showWeuiDialog(config) {
if (config.templateUrl) {
$.ajax({
url: config.templateUrl,
dataType: 'html',
success: function (template) {
buildDialog(template);
}
});
} else {
buildDialog(config.template);
}
function buildDialog(template) {
var defaultConfig = {backdrop: true};
config = $.extend({}, defaultConfig, config);
var dialog = $("<div></div>", {class: 'weui_dialog_confirm'});
var mask = $('<div></div>', {class: 'weui_mask'}).appendTo(dialog);
if (config.backdrop) {
mask.click(function () {
dialog.remove();
if ($.isFunction(config.dismiss)) {
config.dismiss();
}
})
}
var dialogBox = $("<div></div>", {class: 'weui_dialog'}).appendTo(dialog);
if (config.title) {
$('<div></div>', {class: 'weui_dialog_hd'}).append($('<strong></strong>', {class: 'weui_dialog_title'}).html(config.title)).appendTo(dialogBox);
}
var dialogBody = $("<div></div>", {class: 'weui_dialog_bd'}).appendTo(dialogBox);
if (template) {
dialogBody.append(template);
}
if ($.isFunction(config.initialize)) {
config.initialize(dialog);
}
var ft = $('<div class="weui_dialog_ft"></div>').appendTo(dialogBox);
if ($.isFunction(config.confirm)) {
var yes = $('<a></a>', {
class: 'weui_btn_dialog primary',
text: 'OK',
style: 'background: #FF2D55;color: #fff;'
}).appendTo(ft);
yes.click(function () {
config.confirm(dialog, true);
dialog.remove();
});
var no = $('<a></a>', {class: 'weui_btn_dialog default', text: 'Cancel'}).appendTo(ft);
no.click(function () {
config.confirm(dialog, false);
dialog.remove();
})
} else {
var ok = $('<a></a>', {
class: 'weui_btn_dialog primary',
text: 'OK',
style: 'background: #FF2D55;color: #fff;'
}).appendTo(ft);
ok.click(function () {
dialog.remove();
})
}
dialog.appendTo($('body'));
}
}
function getUserId(){
window.RPayPlus.send("getUserId", null, function(data){
window.RpayUserId = data;
});
}
function pay(param,callback){
var order={
nonce_str:param.nonce_str,
rpay_order_id:param.rpay_order_id,
mch_order_id:param.mch_order_id
};
window.RPayPlus.send('pay', order, callback);
}
function back(){
window.RPayPlus.send("back", null, null);
}
function jsInvoke(){
window.RPayPlus.send("jsInvoke", 'Native Test', null);
}
function createOrder(msg){
alert('create order information='+JSON.stringify(msg));
}
function queryOrder(msg){
alert('query order information='+JSON.stringify(msg));
var order={
orderId:'00001',
amount:'$10.98',
title:'Balance Top-UP'
};
setTimeout("window.RPayPlus.onResult("+JSON.stringify(order)+");", 1500);
}
function registerJs(){
window.RPayPlus.register('createOrder', function(data){
createOrder(data);
});
window.RPayPlus.register('queryOrder', function(data){
queryOrder(data);
});
}
getUserId();
});

@ -0,0 +1,97 @@
/**
* Created by yixian on 2016-07-15.
*/
$(document).ready(function () {
'use strict';
decode();
function decode() {
var redirect = window.redirect;
while(redirect.indexOf('://')<0){
redirect = decodeURIComponent(redirect);
if(redirect==window.redirect){
break;
}
window.redirect = redirect;
}
}
var dataCache = {paying: false};
$('#key_P').bind('touchstart', startPay);
function startPay() {
$('#wdiv').show();
if (dataCache.paying) {
return;
}
dataCache.paying = true;
$.ajax({
url: '/api/v1.0/alipay/partners/' + window.client_moniker + '/orders/'+window.order_id+'/order_params',
method: 'GET',
dataType: 'json',
success: function (pay) {
if (pay.direct_paid) {
location.href = window.redirect;
return;
}
if (window.AlipayJSBridge) {
callPayment();
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', callPayment, false);
}
function callPayment() {
try {
AlipayJSBridge.call('tradePay', {
tradeNO: pay.trade_no
}, function (res) {
dataCache.paying = false;
if (res.resultCode == '9000') {
AlipayJSBridge.call('startApp', {
appId: '20000056',
param: {
actionType: 'showSuccPage',
payResult: res.result
},
closeCurrentApp: false
});
startCheckOrder(window.order_id, window.redirect);
} else {
alert(res.memo);
}
$('#wdiv').hide();
})
} catch (err) {
alert(err);
$('#wdiv').hide();
}
}
},
error: function (jqXhr) {
alert(jqXhr.responseJSON.message);
$('#wdiv').hide();
dataCache.paying = false;
}
})
}
function startCheckOrder(orderId, url) {
function checkOrderStd() {
$.ajax({
url: '/api/v1.0/payment/orders/' + orderId + '/status',
method: 'GET',
dataType: 'json',
success: function (res) {
if (res.paid) {
location.href = url;
} else {
setTimeout(checkOrderStd, 500);
}
}
})
}
checkOrderStd();
}
});

@ -617,6 +617,7 @@ public class CustomerImpressionImplTest {
}
return result;
}
@Test

@ -28,7 +28,7 @@ public class ExportATOReport {
@Test
public void export() throws IOException {
String content = atoReportService.exportBTTPSFile(DateTime.parse("2017-07-01").toDate(), DateTime.parse("2017-07-31").toDate());
FileUtils.write(new File("C:\\Users\\yixian\\Documents\\royalpay2017070120170731.bttps"), content, StandardCharsets.US_ASCII);
String content = atoReportService.exportBTTPSFile(DateTime.parse("2017-07-01").toDate(), DateTime.parse("2018-06-30").toDate());
FileUtils.write(new File("C:\\Users\\yixian\\Documents\\royalpay2017070120180630.bttps"), content, StandardCharsets.US_ASCII);
}
}

Loading…
Cancel
Save