Commit 46e44c95 authored by xuxin's avatar xuxin

Merge remote-tracking branch 'origin/master'

parents a3705daa aa155da0
LOG_ROOT=/logs
#deployment target is production env.
DEPLOY_TARGET=prod
INTELLIGROUP_SERVICE_PASSWORD=123
ACCOUNT_SERVICE_PASSWORD=123
MONGODB_PASSWORD=123
MONGODB_SUPER_PASSWORD=Cdex32eO9
#DOCKER_HOST=tcp://registry-vpc.cn-shenzhen.aliyuncs.com:80
DOCKER_USER=liqingsong@1616554330968404
DOCKER_PASS=Edgec2018
\ No newline at end of file
services:
staging-mongodb:
environment:
MONGODB_PASSWORD: $MONGODB_PASSWORD
MONGODB_SUPER_PASSWORD: $MONGODB_SUPER_PASSWORD
HOST_NAME: staging-mongodb
LOG_ROOT: $LOG_ROOT
image: registry-vpc.cn-shenzhen.aliyuncs.com/cloudam/staging-mongodb
volumes:
- /data/db/browser:/data/db
restart: always
logging:
options:
max-size: "10m"
max-file: "10"
browser:
environment:
MONGODB_PASSWORD: $MONGODB_PASSWORD
spring.profiles.active: staging
LOG_ROOT: $LOG_ROOT
image: registry-vpc.cn-shenzhen.aliyuncs.com/cloudam/browser-staging
volumes:
- /data/logs:$LOG_ROOT
restart: always
logging:
options:
max-size: "10m"
max-file: "10"
\ No newline at end of file
#!/bin/bash
docker rmi -f `docker images | grep '<none>' | awk '{print $3}'`
sudo_token=sudo
deploy=n
if [ "$1" == "win" ]; then
sudo_token=
fi
if [ "$2" == "y" ]; then
deploy=y
fi
export DOCKER_HOST=registry-vpc.cn-shenzhen.aliyuncs.com
export DOCKER_USER=liqingsong@1616554330968404
export DOCKER_PASS=Edgec2018
export COMMIT=`date +%s | md5sum | head -c 10 ; echo`
#export COMMIT="latest"
cd /root/cloudam/browser-backend/
git pull
export TAG="latest"
export runningenv="-staging"
mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
export IMAGE_NAME=cloudam/browser$runningenv
$sudo_token docker build -t $IMAGE_NAME:$COMMIT .
$sudo_token docker tag $IMAGE_NAME:$COMMIT $DOCKER_HOST/$IMAGE_NAME:$TAG
$sudo_token docker push $DOCKER_HOST/$IMAGE_NAME
\ No newline at end of file
cd /root/cloudam
docker rmi -f `docker images | grep '<none>' | awk '{print $3}'`
docker-compose -f browser-staging.yml pull
docker-compose -f browser-staging.yml --compatibility up -d
...@@ -505,6 +505,7 @@ public class AdministratorController { ...@@ -505,6 +505,7 @@ public class AdministratorController {
/** /**
* 专线回落 * 专线回落
*/ */
@PreAuthorize(Securitys.ADMIN_EL)
@PutMapping(value = "/0xadministrator/updateip/{addr}/{flag}") @PutMapping(value = "/0xadministrator/updateip/{addr}/{flag}")
public ResultDto updateIp(@PathVariable String addr, @PathVariable String flag) { public ResultDto updateIp(@PathVariable String addr, @PathVariable String flag) {
ResultDto resultDto = new ResultDto(); ResultDto resultDto = new ResultDto();
...@@ -518,6 +519,29 @@ public class AdministratorController { ...@@ -518,6 +519,29 @@ public class AdministratorController {
} }
return resultDto; return resultDto;
} }
/**
* 设置客户为分销商
*/
@PreAuthorize(Securitys.ADMIN_EL)
@PutMapping(value = "/0xadministrator/account/{id}/{flag}")
public ResultDto updateToDistributor(@PathVariable String id, @PathVariable Integer flag) {
ResultDto resultDto = new ResultDto();
try {
boolean tag = false;
if (flag == 1) {
tag = true;
}
Long i = administratorService.convertToDistributor(id, tag);
resultDto.setStatus(0);
resultDto.setData(i);
} catch (Exception e) {
resultDto.setStatus(-1);
resultDto.setData(e.getMessage());
}
return resultDto;
}
} }
......
package com.edgec.browserbackend.account.controller;
import com.edgec.browserbackend.account.service.PayBackService;
import com.edgec.browserbackend.browser.domain.PayBack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author xuxin
* @date 2020/7/24 15:19
* @description 充值满赠
*/
@RestController
@RequestMapping("/payback")
public class PayBackServiceController {
@Autowired
private PayBackService payBackService;
@GetMapping(path = "/all")
public List<PayBack> getAll() {
return payBackService.findAll();
}
}
...@@ -38,6 +38,11 @@ public class Promotion { ...@@ -38,6 +38,11 @@ public class Promotion {
*/ */
private boolean isSale; private boolean isSale;
/**
* 是否为分销商
*/
private boolean isDistributor;
/** /**
* 当月礼金 * 当月礼金
*/ */
...@@ -124,4 +129,12 @@ public class Promotion { ...@@ -124,4 +129,12 @@ public class Promotion {
public void setTotalCommission(int totalCommission) { public void setTotalCommission(int totalCommission) {
this.totalCommission = totalCommission; this.totalCommission = totalCommission;
} }
public boolean isDistributor() {
return isDistributor;
}
public void setDistributor(boolean distributor) {
isDistributor = distributor;
}
} }
...@@ -15,7 +15,7 @@ public class UserPayment { ...@@ -15,7 +15,7 @@ public class UserPayment {
@Id @Id
private String id; private String id;
private String tradeNo = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+SmsUtils.createRandom(true, 4); private String tradeNo = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + SmsUtils.createRandom(true, 4);
private String username; private String username;
...@@ -23,6 +23,10 @@ public class UserPayment { ...@@ -23,6 +23,10 @@ public class UserPayment {
private boolean succeed; private boolean succeed;
/**
* 感觉这个时间记录的是订单创建时间不太合理
* 在业务中修改为 我们系统中记录的订单充值成功的时间
*/
private Date paymentDate = new Date(); private Date paymentDate = new Date();
private PaymentMethod paymentMethod; private PaymentMethod paymentMethod;
......
...@@ -12,4 +12,6 @@ public interface AccountRepositoryCustom { ...@@ -12,4 +12,6 @@ public interface AccountRepositoryCustom {
Account findByPromotion(String code); Account findByPromotion(String code);
Long convertToDistributor(String id, boolean tag);
} }
package com.edgec.browserbackend.account.repository; package com.edgec.browserbackend.account.repository;
import com.edgec.browserbackend.account.domain.Account; import com.edgec.browserbackend.account.domain.Account;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document; import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.MongoTemplate;
...@@ -63,4 +64,18 @@ public class AccountRepositoryCustomImpl implements AccountRepositoryCustom { ...@@ -63,4 +64,18 @@ public class AccountRepositoryCustomImpl implements AccountRepositoryCustom {
return null; return null;
return account; return account;
} }
@Override
public Long convertToDistributor(String id, boolean tag) {
Document doc = new Document();
BasicQuery basicQuery = new BasicQuery(doc);
basicQuery.addCriteria(where("_id").is(id));
Update update = new Update();
update.set("promotion.isDistributor", tag);
UpdateResult upsert = mongoTemplate.upsert(basicQuery, update, Account.class);
return upsert.getModifiedCount();
}
} }
...@@ -3,8 +3,10 @@ package com.edgec.browserbackend.account.repository; ...@@ -3,8 +3,10 @@ package com.edgec.browserbackend.account.repository;
import com.edgec.browserbackend.account.domain.UserPayment; import com.edgec.browserbackend.account.domain.UserPayment;
import java.util.Date;
public interface UserPaymentRepositoryCustom { public interface UserPaymentRepositoryCustom {
boolean updatePaymentResult(UserPayment payment, boolean result); boolean updatePaymentResult(UserPayment payment, boolean result, Date paymentDate);
} }
...@@ -8,6 +8,8 @@ import org.springframework.data.mongodb.core.MongoTemplate; ...@@ -8,6 +8,8 @@ import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
import java.util.Date;
import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Criteria.where;
public class UserPaymentRepositoryCustomImpl implements UserPaymentRepositoryCustom { public class UserPaymentRepositoryCustomImpl implements UserPaymentRepositoryCustom {
...@@ -16,18 +18,16 @@ public class UserPaymentRepositoryCustomImpl implements UserPaymentRepositoryCus ...@@ -16,18 +18,16 @@ public class UserPaymentRepositoryCustomImpl implements UserPaymentRepositoryCus
private MongoTemplate mongoTemplate; private MongoTemplate mongoTemplate;
@Override @Override
public boolean updatePaymentResult(UserPayment payment, boolean result) { public boolean updatePaymentResult(UserPayment payment, boolean result, Date paymentDate) {
Document doc = new Document(); Document doc = new Document();
BasicQuery basicQuery = new BasicQuery(doc); BasicQuery basicQuery = new BasicQuery(doc);
basicQuery.addCriteria(where("id").is(payment.getId()).and("succeed").is(!result)); basicQuery.addCriteria(where("id").is(payment.getId()).and("succeed").is(!result));
Update update = new Update(); Update update = new Update();
update.set("succeed", result); update.set("succeed", result);
update.set("paymentDate", paymentDate);
UpdateResult operation = mongoTemplate.updateFirst(basicQuery, update, UserPayment.class); UpdateResult operation = mongoTemplate.updateFirst(basicQuery, update, UserPayment.class);
if (operation.getModifiedCount() < 1) return operation.getModifiedCount() >= 1;
return false;
else
return true;
} }
} }
...@@ -5,13 +5,10 @@ import com.edgec.browserbackend.account.dto.BillQueryResultDto; ...@@ -5,13 +5,10 @@ import com.edgec.browserbackend.account.dto.BillQueryResultDto;
import com.edgec.browserbackend.account.dto.IpCountQueryResultDto; import com.edgec.browserbackend.account.dto.IpCountQueryResultDto;
import com.edgec.browserbackend.account.dto.PromotionQueryResultDto; import com.edgec.browserbackend.account.dto.PromotionQueryResultDto;
import com.edgec.browserbackend.account.dto.UserUsedDto; import com.edgec.browserbackend.account.dto.UserUsedDto;
import com.edgec.browserbackend.browser.domain.IpResource;
import com.edgec.browserbackend.browser.dto.IpResourceDto;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import java.io.File; import java.io.File;
import java.util.HashMap;
import java.util.List; import java.util.List;
public interface AdministratorService { public interface AdministratorService {
...@@ -68,4 +65,8 @@ public interface AdministratorService { ...@@ -68,4 +65,8 @@ public interface AdministratorService {
File getProxyConfig(); File getProxyConfig();
Page<UserUsedDto> getAllUserUsed(Pageable pageable); Page<UserUsedDto> getAllUserUsed(Pageable pageable);
Long convertToDistributor(String id, boolean tag);
} }
package com.edgec.browserbackend.account.service;
import com.edgec.browserbackend.browser.domain.PayBack;
import java.util.List;
/**
* @author xuxin
* @date 2020/7/24 15:14
* @description
*/
public interface PayBackService {
List<PayBack> findAll();
}
...@@ -466,15 +466,14 @@ public class AccountServiceImpl implements AccountService { ...@@ -466,15 +466,14 @@ public class AccountServiceImpl implements AccountService {
com.edgec.browserbackend.common.commons.utils.SmsUtils.sendNewAccountSms("15919921106", com.edgec.browserbackend.common.commons.utils.SmsUtils.SmsTemplateCode.NEWACCOUNT, param); com.edgec.browserbackend.common.commons.utils.SmsUtils.sendNewAccountSms("15919921106", com.edgec.browserbackend.common.commons.utils.SmsUtils.SmsTemplateCode.NEWACCOUNT, param);
com.edgec.browserbackend.common.commons.utils.SmsUtils.sendNewAccountSms("13570690305", com.edgec.browserbackend.common.commons.utils.SmsUtils.SmsTemplateCode.NEWACCOUNT, param); com.edgec.browserbackend.common.commons.utils.SmsUtils.sendNewAccountSms("13570690305", com.edgec.browserbackend.common.commons.utils.SmsUtils.SmsTemplateCode.NEWACCOUNT, param);
// 6. 使用手机注册就送 12 元体验金 // 6. 使用手机注册且填写了正确的邀请码就送 16 元体验金
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
list.add("167"); list.add("167");
list.add("171"); list.add("171");
list.add("184"); list.add("184");
list.add("170"); list.add("170");
if (!StringUtils.isEmpty(account.getPhoneNumber()) && !list.contains(account.getPhoneNumber().substring(0, 3)) && inviter != null) {
if (!StringUtils.isEmpty(account.getPhoneNumber()) && !list.contains(account.getPhoneNumber().substring(0, 3))) { paymentService.bankTransferInsertion(account.getName(), 16);
paymentService.bankTransferInsertion(account.getName(), 12);
} }
log.info("new account has been created: " + account.getName()); log.info("new account has been created: " + account.getName());
......
...@@ -72,6 +72,7 @@ public class AdministratorServiceImpl implements AdministratorService { ...@@ -72,6 +72,7 @@ public class AdministratorServiceImpl implements AdministratorService {
@Autowired @Autowired
private IpCountRecordRepository ipCountRecordRepository; private IpCountRecordRepository ipCountRecordRepository;
@Override @Override
public Administrator createAdministrator(Administrator administrator) { public Administrator createAdministrator(Administrator administrator) {
Administrator administrator1 = new Administrator(); Administrator administrator1 = new Administrator();
...@@ -537,6 +538,11 @@ public class AdministratorServiceImpl implements AdministratorService { ...@@ -537,6 +538,11 @@ public class AdministratorServiceImpl implements AdministratorService {
return userUsedDtopage; return userUsedDtopage;
} }
@Override
public Long convertToDistributor(String id, boolean tag) {
return accountRepository.convertToDistributor(id, tag);
}
} }
......
package com.edgec.browserbackend.account.service.impl;
import com.edgec.browserbackend.account.service.PayBackService;
import com.edgec.browserbackend.browser.domain.PayBack;
import com.edgec.browserbackend.browser.repository.PayBackRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author xuxin
* @date 2020/7/24 15:15
* @description
*/
@Service
public class PayBackServiceImpl implements PayBackService {
@Autowired
private PayBackRepository payBackRepository;
@Override
public List<PayBack> findAll() {
return payBackRepository.findAll();
}
}
...@@ -556,7 +556,6 @@ public class PaymentServiceImpl implements PaymentService { ...@@ -556,7 +556,6 @@ public class PaymentServiceImpl implements PaymentService {
result.setBalance(Math.round(balance.getBalanced())); result.setBalance(Math.round(balance.getBalanced()));
} }
boolean isVpsClient = true; boolean isVpsClient = true;
WXPayConfig ourWxPayConfig = isVpsClient ? new FGLWxConfig() : new CloudamWxConfig(); WXPayConfig ourWxPayConfig = isVpsClient ? new FGLWxConfig() : new CloudamWxConfig();
WXPay wxPay = new WXPay(ourWxPayConfig); WXPay wxPay = new WXPay(ourWxPayConfig);
...@@ -576,8 +575,7 @@ public class PaymentServiceImpl implements PaymentService { ...@@ -576,8 +575,7 @@ public class PaymentServiceImpl implements PaymentService {
result.setStatus(respData.get("trade_state")); result.setStatus(respData.get("trade_state"));
if ("SUCCESS".equals(respData.get("trade_state"))) { if ("SUCCESS".equals(respData.get("trade_state"))) {
byTradeNo.setSucceed(true); byTradeNo.setSucceed(true);
boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true, new Date());
boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true);
if (b) { if (b) {
if (balance == null) { if (balance == null) {
...@@ -644,7 +642,7 @@ public class PaymentServiceImpl implements PaymentService { ...@@ -644,7 +642,7 @@ public class PaymentServiceImpl implements PaymentService {
if ("TRADE_SUCCESS".equals(response.getTradeStatus()) || "TRADE_FINISHED".equals(response.getTradeStatus())) { if ("TRADE_SUCCESS".equals(response.getTradeStatus()) || "TRADE_FINISHED".equals(response.getTradeStatus())) {
byTradeNo.setSucceed(true); byTradeNo.setSucceed(true);
boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true); boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true, new Date());
if (b) { if (b) {
...@@ -791,7 +789,7 @@ public class PaymentServiceImpl implements PaymentService { ...@@ -791,7 +789,7 @@ public class PaymentServiceImpl implements PaymentService {
private void dealPaySuccess(int chargeType, UserPaymentDto result, UserPayment byTradeNo, Account byName, UserBalance balance) { private void dealPaySuccess(int chargeType, UserPaymentDto result, UserPayment byTradeNo, Account byName, UserBalance balance) {
byTradeNo.setSucceed(true); byTradeNo.setSucceed(true);
// 2.1 更新 userPayment 的支付状态为成功 // 2.1 更新 userPayment 的支付状态为成功
boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true); boolean b = userPaymentRepository.updatePaymentResult(byTradeNo, true, new Date());
if (b) { if (b) {
log.info("订单 " + byTradeNo.getTradeNo() + " 的支付状态更新为成功"); log.info("订单 " + byTradeNo.getTradeNo() + " 的支付状态更新为成功");
// 2.2 获取充值优惠赠送 // 2.2 获取充值优惠赠送
......
...@@ -14,8 +14,6 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.A ...@@ -14,8 +14,6 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.A
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
/** /**
* @author cdov * @author cdov
...@@ -49,16 +47,16 @@ public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdap ...@@ -49,16 +47,16 @@ public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdap
// @formatter:off // @formatter:off
clients.inMemory() clients.inMemory()
.withClient("browser") .withClient("browser")
.authorizedGrantTypes("refresh_token", "password") .authorizedGrantTypes("refresh_token", "password")
.scopes("browser") .scopes("browser")
.accessTokenValiditySeconds(43200) .accessTokenValiditySeconds(7 * 24 * 60 * 60)
.refreshTokenValiditySeconds(43200) .refreshTokenValiditySeconds(30 * 24 * 60 * 60)
.and() .and()
.withClient("cloudam-browser") .withClient("cloudam-browser")
.secret(env.getProperty("ACCOUNT_SERVICE_PASSWORD")) .secret(env.getProperty("ACCOUNT_SERVICE_PASSWORD"))
.authorizedGrantTypes("client_credentials", "refresh_token") .authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("server"); .scopes("server");
// @formatter:on // @formatter:on
} }
......
package com.edgec.browserbackend.browser.controller;
import com.edgec.browserbackend.account.dto.ResultDto;
import com.edgec.browserbackend.browser.service.GlobalFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xuxin
* @date 2020/8/3 18:28
* @description
*/
@RestController
@RequestMapping("/globalfield")
public class GlobalFieldController {
@Autowired
private GlobalFieldService globalFieldService;
@GetMapping("/speciallinestate")
public ResultDto querySpecialLineState() {
ResultDto resultDto = new ResultDto();
resultDto.setStatus(0);
resultDto.setData(globalFieldService.querySpecialLineState());
return resultDto;
}
}
...@@ -232,6 +232,33 @@ public class ShopController { ...@@ -232,6 +232,33 @@ public class ShopController {
} }
/**
* 获取cookie
*/
@GetMapping("/cookie/{shopId}")
public ResultDto getShopCookie(@PathVariable String shopId) {
String cookie = shopService.queryShopCookieById(shopId);
ResultDto resultDto = new ResultDto();
resultDto.setStatus(0);
resultDto.setData(cookie);
return resultDto;
}
/**
* 删除cookie
*/
@DeleteMapping("/cookie/{shopId}")
public ResultDto delShopCookie(@PathVariable String shopId) {
Integer result = shopService.deleteShopCookieById(shopId);
ResultDto resultDto = new ResultDto();
resultDto.setStatus(result);
return resultDto;
}
private void dealClientRequestException(ResultDto resultDto, ClientRequestException e) { private void dealClientRequestException(ResultDto resultDto, ClientRequestException e) {
resultDto.setStatus(-1); resultDto.setStatus(-1);
Map<String, Object> statusInfo = new HashMap<>(); Map<String, Object> statusInfo = new HashMap<>();
......
package com.edgec.browserbackend.browser.domain;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.math.BigDecimal;
/**
* @author xuxin
* @date 2020/8/3 14:37
* @description 用来存放一些全局变量
*/
@Data
@Document(collection = "globalfield")
public class GlobalField {
@Id
private String id;
/**
* 专线状态
* on:正常
* off: 挂掉了
*/
private String specialLineState;
/**
* 注册礼金
* 目前是注册就送 16 元
*/
private Integer registerGift;
/**
* 分销商提成比例
* 目前是 0.30
*/
private BigDecimal distributorRate;
}
...@@ -10,7 +10,7 @@ import org.springframework.data.mongodb.core.mapping.Document; ...@@ -10,7 +10,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
*/ */
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@Document(collection = "UserCode") @Document(collection = "usercode")
public class UserCode { public class UserCode {
@Id @Id
private String username; private String username;
......
package com.edgec.browserbackend.browser.repository;
import com.edgec.browserbackend.browser.domain.GlobalField;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @author xuxin
* @date 2020/8/3 16:54
* @description
*/
public interface GlobalFieldRepository extends MongoRepository<GlobalField, String> {
}
package com.edgec.browserbackend.browser.repository;
/**
* @author xuxin
* @date 2020/8/3 17:00
* @description
*/
public interface GlobalFieldRepositoryCustom {
}
package com.edgec.browserbackend.browser.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
/**
* @author xuxin
* @date 2020/8/3 17:02
* @description
*/
public class GlobalFieldRepositoryCustomImpl implements GlobalFieldRepositoryCustom {
@Autowired
private MongoTemplate mongoTemplate;
}
...@@ -34,4 +34,6 @@ public interface IpResourceRepositoryCustom { ...@@ -34,4 +34,6 @@ public interface IpResourceRepositoryCustom {
List<IpResource> findShopIdInListAndStatus(List<String> shopIds, boolean isDeleted, int status); List<IpResource> findShopIdInListAndStatus(List<String> shopIds, boolean isDeleted, int status);
List<IpResource> findShopIdInListAndRegionLike(List<String> shopIds, boolean isDeleted, String region); List<IpResource> findShopIdInListAndRegionLike(List<String> shopIds, boolean isDeleted, String region);
List<IpResource> specialLineCheckTask();
} }
...@@ -15,6 +15,8 @@ import org.springframework.data.mongodb.core.query.Update; ...@@ -15,6 +15,8 @@ import org.springframework.data.mongodb.core.query.Update;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.sample;
import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Criteria.where;
public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCustom { public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCustom {
...@@ -73,7 +75,7 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto ...@@ -73,7 +75,7 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto
MatchOperation match = Aggregation.match(matchCriteria); MatchOperation match = Aggregation.match(matchCriteria);
SampleOperation sample = Aggregation.sample(100); SampleOperation sample = sample(100);
AggregationResults<IpResource> results = mongoTemplate.aggregate(Aggregation.newAggregation(match, sample), IpResource.class, IpResource.class); AggregationResults<IpResource> results = mongoTemplate.aggregate(Aggregation.newAggregation(match, sample), IpResource.class, IpResource.class);
List<IpResource> mappedResults = results.getMappedResults(); List<IpResource> mappedResults = results.getMappedResults();
...@@ -90,7 +92,7 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto ...@@ -90,7 +92,7 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto
MatchOperation match = Aggregation.match(matchCriteria); MatchOperation match = Aggregation.match(matchCriteria);
SampleOperation sample = Aggregation.sample(20); SampleOperation sample = sample(20);
AggregationResults<IpResource> results = mongoTemplate.aggregate(Aggregation.newAggregation(match, sample), IpResource.class, IpResource.class); AggregationResults<IpResource> results = mongoTemplate.aggregate(Aggregation.newAggregation(match, sample), IpResource.class, IpResource.class);
List<IpResource> mappedResults = results.getMappedResults(); List<IpResource> mappedResults = results.getMappedResults();
...@@ -214,5 +216,22 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto ...@@ -214,5 +216,22 @@ public class IpResourceRepositoryCustomImpl implements IpResourceRepositoryCusto
return result; return result;
} }
@Override
public List<IpResource> specialLineCheckTask() {
AggregationOperation match = Aggregation.match(
Criteria.where("status").in(Arrays.asList(0L, 2L))
.and("specialLine").is(true)
.and("bind").is(true)
.and("isDeleted").is(false)
.and("validTime").gt(Instant.now().toEpochMilli())
);
AggregationOperation sample = sample(20);
Aggregation aggregation = newAggregation(match, sample);
AggregationResults<IpResource> results = mongoTemplate.aggregate(aggregation, IpResource.class, IpResource.class);
List<IpResource> list = results.getMappedResults();
return list;
}
} }
package com.edgec.browserbackend.browser.service;
/**
* @author xuxin
* @date 2020/8/3 18:03
* @description
*/
public interface GlobalFieldService {
String querySpecialLineState();
}
package com.edgec.browserbackend.browser.service.Impl;
import com.edgec.browserbackend.browser.repository.GlobalFieldRepository;
import com.edgec.browserbackend.browser.service.GlobalFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author xuxin
* @date 2020/8/3 18:04
* @description
*/
@Service
public class GlobalFieldServiceImpl implements GlobalFieldService {
@Autowired
private GlobalFieldRepository globalFieldRepository;
@Override
public String querySpecialLineState() {
String state = "on";
if (!globalFieldRepository.findAll().isEmpty()) {
state = globalFieldRepository.findAll().get(0).getSpecialLineState();
}
return state;
}
}
...@@ -131,7 +131,7 @@ public class IpAndShopServiceImpl implements IpAndShopService { ...@@ -131,7 +131,7 @@ public class IpAndShopServiceImpl implements IpAndShopService {
// 7. 更新 ip 资源的绑定状态为 未绑定 // 7. 更新 ip 资源的绑定状态为 未绑定
IpResource newIp = ipResourceRepository.findById(ipResource.getId()).orElse(null); IpResource newIp = ipResourceRepository.findById(ipResource.getId()).orElse(null);
if (newIp.getShopIds() == null || !newIp.getShopIds().contains(shopId)) { if (newIp.getShopIds() == null || newIp.getShopIds().isEmpty()) {
ipResourceRepository.updateBind(ipResource.getId(), false); ipResourceRepository.updateBind(ipResource.getId(), false);
} }
} catch (Exception e) { } catch (Exception e) {
......
...@@ -460,7 +460,7 @@ public class ShopServiceImpl implements ShopService { ...@@ -460,7 +460,7 @@ public class ShopServiceImpl implements ShopService {
IpResourceRequestDto ipResourceRequestDto1 = new IpResourceRequestDto(); IpResourceRequestDto ipResourceRequestDto1 = new IpResourceRequestDto();
ipResourceRequestDto1.setAddr(Arrays.asList(ipResource.getAddr())); ipResourceRequestDto1.setAddr(Arrays.asList(ipResource.getAddr()));
try { try {
ipResourceService.deleteIp(username, ipResourceRequestDto1); ipResourceService.deleteExpiredIp(username, ipResourceRequestDto1);
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
...@@ -468,7 +468,7 @@ public class ShopServiceImpl implements ShopService { ...@@ -468,7 +468,7 @@ public class ShopServiceImpl implements ShopService {
IpResourceRequestDto ipResourceRequestDto1 = new IpResourceRequestDto(); IpResourceRequestDto ipResourceRequestDto1 = new IpResourceRequestDto();
ipResourceRequestDto1.setIpId(Arrays.asList(ipResource.getId())); ipResourceRequestDto1.setIpId(Arrays.asList(ipResource.getId()));
try { try {
ipResourceService.deleteIp(username, ipResourceRequestDto1); ipResourceService.deleteExpiredIp(username, ipResourceRequestDto1);
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
...@@ -649,6 +649,25 @@ public class ShopServiceImpl implements ShopService { ...@@ -649,6 +649,25 @@ public class ShopServiceImpl implements ShopService {
return result; return result;
} }
@Override
public String queryShopCookieById(String id) {
Shop shop = shopRepository.findById(id).orElseThrow(() -> new ClientRequestException(BrowserErrorCode.SHOPNOTEXIST));
return shop.getShopCookie();
}
@Override
public Integer deleteShopCookieById(String id) {
Shop shop = shopRepository.findById(id).orElseThrow(() -> new ClientRequestException(BrowserErrorCode.SHOPNOTEXIST));
shop.setShopCookie("");
Shop save = shopRepository.save(shop);
Integer i = 1;
if (StringUtils.isEmpty(save.getShopCookie())) {
i = 0;
}
return i;
}
private String getShopId(String username, ShopResultDto shopResultDto) { private String getShopId(String username, ShopResultDto shopResultDto) {
Shop shop = new Shop(); Shop shop = new Shop();
shopResultDto.setOwner(username); shopResultDto.setOwner(username);
......
package com.edgec.browserbackend.browser.service; package com.edgec.browserbackend.browser.service;
import com.edgec.browserbackend.browser.domain.*; import com.edgec.browserbackend.browser.domain.IpOptions;
import com.edgec.browserbackend.browser.domain.IpSummary;
import com.edgec.browserbackend.browser.domain.PlatformOptions;
import com.edgec.browserbackend.browser.dto.*; import com.edgec.browserbackend.browser.dto.*;
import java.util.List; import java.util.List;
...@@ -13,6 +15,8 @@ public interface IpResourceService { ...@@ -13,6 +15,8 @@ public interface IpResourceService {
IpOperationResultDto deleteIp(String username, IpResourceRequestDto ipResourceRequestDto) throws Exception; IpOperationResultDto deleteIp(String username, IpResourceRequestDto ipResourceRequestDto) throws Exception;
IpOperationResultDto deleteExpiredIp(String username, IpResourceRequestDto ipResourceRequestDto);
IpPageResultDto getIpList(String username, int groupType, int page, int amount, IpFilterDto ipFilterDto); IpPageResultDto getIpList(String username, int groupType, int page, int amount, IpFilterDto ipFilterDto);
void setIpOptions(); void setIpOptions();
......
...@@ -34,4 +34,8 @@ public interface ShopService { ...@@ -34,4 +34,8 @@ public interface ShopService {
List<String> getBatchShopUsers(String username, List<String> shopIds); List<String> getBatchShopUsers(String username, List<String> shopIds);
Integer dealDirtyData(); Integer dealDirtyData();
String queryShopCookieById(String id);
Integer deleteShopCookieById(String id);
} }
...@@ -5,6 +5,7 @@ import com.edgec.browserbackend.account.domain.Promotion; ...@@ -5,6 +5,7 @@ import com.edgec.browserbackend.account.domain.Promotion;
import com.edgec.browserbackend.account.domain.UserPrePaidBilling; import com.edgec.browserbackend.account.domain.UserPrePaidBilling;
import com.edgec.browserbackend.account.repository.AccountRepository; import com.edgec.browserbackend.account.repository.AccountRepository;
import com.edgec.browserbackend.account.repository.UserPrePaidBillingRepository; import com.edgec.browserbackend.account.repository.UserPrePaidBillingRepository;
import com.edgec.browserbackend.browser.repository.GlobalFieldRepository;
import net.javacrumbs.shedlock.core.SchedulerLock; import net.javacrumbs.shedlock.core.SchedulerLock;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -27,6 +28,8 @@ public class PromotionTask { ...@@ -27,6 +28,8 @@ public class PromotionTask {
@Autowired @Autowired
private UserPrePaidBillingRepository userPrePaidBillingRepository; private UserPrePaidBillingRepository userPrePaidBillingRepository;
private GlobalFieldRepository globalFieldRepository;
// TODO 2020年7月2号, 晚上11点,jim负责跟踪下 // TODO 2020年7月2号, 晚上11点,jim负责跟踪下
@SchedulerLock(name = "countGift", lockAtLeastForString = "PT1H", lockAtMostForString = "PT2H") @SchedulerLock(name = "countGift", lockAtLeastForString = "PT1H", lockAtMostForString = "PT2H")
...@@ -72,6 +75,11 @@ public class PromotionTask { ...@@ -72,6 +75,11 @@ public class PromotionTask {
if (account.getPromotion().isSale()) { if (account.getPromotion().isSale()) {
promotion.setGift(totalCommission * 0.1 + secondCommission * 0.02); promotion.setGift(totalCommission * 0.1 + secondCommission * 0.02);
} }
if (account.getPromotion().isDistributor()) {
promotion.setGift(totalCommission * globalFieldRepository.findAll().get(0).getDistributorRate().doubleValue());
}
promotion.setAllGift(promotion.getAllGift() + promotion.getGift()); promotion.setAllGift(promotion.getAllGift() + promotion.getGift());
accountRepository.save(account); accountRepository.save(account);
} }
...@@ -113,10 +121,15 @@ public class PromotionTask { ...@@ -113,10 +121,15 @@ public class PromotionTask {
// 3. 封装当前账户的返佣相关信息(当月当前的消费、当月当前的返佣)并保存 // 3. 封装当前账户的返佣相关信息(当月当前的消费、当月当前的返佣)并保存
Promotion promotion = account.getPromotion(); Promotion promotion = account.getPromotion();
promotion.setCommission((int) totalCommission); promotion.setCommission((int) totalCommission);
// 4. 不同角色的人给不同的提成
promotion.setGift(totalCommission * 0.08); promotion.setGift(totalCommission * 0.08);
if (account.getPromotion().isSale()) { if (account.getPromotion().isSale()) {
promotion.setGift(totalCommission * 0.1 + secondCommission * 0.02); promotion.setGift(totalCommission * 0.1 + secondCommission * 0.02);
} }
if (account.getPromotion().isDistributor()) {
promotion.setGift(totalCommission * globalFieldRepository.findAll().get(0).getDistributorRate().doubleValue());
}
accountRepository.save(account); accountRepository.save(account);
} }
log.info("End scheduled task:Scheduled.countCommission..."); log.info("End scheduled task:Scheduled.countCommission...");
......
...@@ -64,6 +64,7 @@ public class Set3proxyTask { ...@@ -64,6 +64,7 @@ public class Set3proxyTask {
bw.write("fakeresolve\n"); bw.write("fakeresolve\n");
bw.write("config /root/3proxy.cfg\n"); bw.write("config /root/3proxy.cfg\n");
bw.write("monitor /root/3proxy.cfg\n"); bw.write("monitor /root/3proxy.cfg\n");
bw.write("deny * * $/root/blacklist.cfg\n");
for (IpResource ipResource : ipResources) { for (IpResource ipResource : ipResources) {
if (StringUtils.isNotBlank(ipResource.getAddr())) if (StringUtils.isNotBlank(ipResource.getAddr()))
......
package com.edgec.browserbackend.browser.task;
import com.edgec.browserbackend.account.domain.QueryIpUrlList;
import com.edgec.browserbackend.account.repository.QueryIpUrlListRepository;
import com.edgec.browserbackend.browser.domain.GlobalField;
import com.edgec.browserbackend.browser.domain.IpResource;
import com.edgec.browserbackend.browser.repository.GlobalFieldRepository;
import com.edgec.browserbackend.browser.repository.IpResourceRepository;
import com.edgec.browserbackend.common.utils.Trans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* @author xuxin
* @date 2020/8/3 14:29
* @description
*/
@Component
public class SpecialLineCheckTask {
private static final Logger log = LoggerFactory.getLogger(SpecialLineCheckTask.class);
@Autowired
private IpResourceRepository ipResourceRepository;
@Autowired
private QueryIpUrlListRepository queryIpUrlListRepository;
@Autowired
private GlobalFieldRepository globalFieldRepository;
@Scheduled(cron = "0 0/5 * * * ?")
public void healthCheck() {
// 1. 随机获取符合条件的 20 个 ip
List<IpResource> ipResourceList = ipResourceRepository.specialLineCheckTask();
// 2. 对获取的ip进行检查
int[] arr = getCheckArray(ipResourceList);
int finalSuccess = arr[0];
int finalFail = arr[1];
GlobalField globalField = getGlobalField();
// 3. 获取 specialLine 的状态,并判断是否需要更新数据库状态
String specialLineState = null;
if ("on".equals(globalField.getSpecialLineState())) {
specialLineState = finalFail == ipResourceList.size() ? "off" : null;
}
if ("off".equals(globalField.getSpecialLineState())) {
specialLineState = finalSuccess > 1 ? "on" : null;
}
if (!StringUtils.isEmpty(specialLineState)) {
globalField.setSpecialLineState(specialLineState);
globalFieldRepository.save(globalField);
}
}
private int[] getCheckArray(List<IpResource> ipResourceList) {
List<QueryIpUrlList> queryIpUrlLists = queryIpUrlListRepository.findAll();
int finalSuccess = 0;
int finalFail = 0;
for (IpResource ipResource : ipResourceList) {
int success = 0;
for (QueryIpUrlList queryIpUrlList : queryIpUrlLists) {
Trans trans = new Trans(ipResource.getProxyUsername(), ipResource.getProxyPassword());
String result = trans.get(queryIpUrlList.getUrl());
if (result.contains(ipResource.getAddr())) {
success++;
break;
}
}
if (success == 0) {
finalFail++;
}
if (success == 1) {
finalSuccess++;
}
// 用于性能优化
if (finalSuccess == 2) {
break;
}
}
int[] arr = {finalSuccess, finalFail};
return arr;
}
private GlobalField getGlobalField() {
List<GlobalField> globalFieldList = globalFieldRepository.findAll();
GlobalField globalField = null;
if (globalFieldList.isEmpty()) {
GlobalField g = new GlobalField();
g.setSpecialLineState("on");
globalField = globalFieldRepository.save(g);
} else {
globalField = globalFieldList.get(0);
}
return globalField;
}
}
...@@ -73,4 +73,4 @@ spring: ...@@ -73,4 +73,4 @@ spring:
profiles: staging profiles: staging
data: data:
mongodb: mongodb:
uri: mongodb://user:${MONGODB_PASSWORD}@localhost:27017/browser uri: mongodb://user:${MONGODB_PASSWORD}@staging-mongodb:27017/browser
\ No newline at end of file \ No newline at end of file
...@@ -50,123 +50,111 @@ ...@@ -50,123 +50,111 @@
"本地" "本地"
] ]
}, },
"ipPlatForm": { "ipPlatForm": {
"中国随机": [ "中国随机": [
"阿里云-68-38", "阿里云-68-49",
"腾讯云-68-49"
"腾讯云-68-38"
], ],
"杭州": [ "杭州": [
"阿里云-68-38" "阿里云-68-49"
], ],
"上海": [ "上海": [
"阿里云-68-38" "阿里云-68-49"
], ],
"深圳": [ "深圳": [
"阿里云-68-38" "阿里云-68-49"
], ],
"广州": [ "广州": [
"阿里云-68-38", "阿里云-68-49",
"腾讯云-68-38" "腾讯云-68-49"
], ],
"北京": [ "北京": [
"阿里云-68-38" "阿里云-68-49"
], ],
"青岛": [ "青岛": [
"阿里云-68-38" "阿里云-68-49"
], ],
"张家口": [ "张家口": [
"阿里云-68-38" "阿里云-68-49"
], ],
"呼和浩特": [ "呼和浩特": [
"阿里云-68-38" "阿里云-68-49"
], ],
"成都": [ "成都": [
"阿里云-68-38" "阿里云-68-49"
], ],
"河源": [ "河源": [
"阿里云-68-38" "阿里云-68-49"
], ],
"香港": [ "香港": [
"阿里云-68-38" "阿里云-68-49"
], ],
"美国随机": [ "美国随机": [
"阿里云-58-38", "阿里云-58-49",
"亚马逊云-58-38" "亚马逊云-58-49"
], ],
"加利福尼亚": [ "加利福尼亚": [
"亚马逊云-58-38", "亚马逊云-58-49",
"阿里云-58-38" "阿里云-58-49"
], ],
"弗吉尼亚": [ "弗吉尼亚": [
"阿里云-58-38", "阿里云-58-49",
"亚马逊云-58-38" "亚马逊云-58-49"
], ],
"俄勒冈": [ "俄勒冈": [
"亚马逊云-58-38" "亚马逊云-58-49"
], ],
"俄亥俄": [ "俄亥俄": [
"亚马逊云-58-38" "亚马逊云-58-49"
], ],
"英国-伦敦": [ "英国-伦敦": [
"阿里云-88-38", "阿里云-88-49",
"亚马逊云-88-38" "亚马逊云-88-49"
], ],
"德国-法兰克福": [ "德国-法兰克福": [
"阿里云-88-38", "阿里云-88-49",
"亚马逊云-88-38" "亚马逊云-88-49"
], ],
"俄罗斯-莫斯科": [ "俄罗斯-莫斯科": [
"腾讯云-88-38" "腾讯云-88-49"
], ],
"法国-巴黎": [ "法国-巴黎": [
"亚马逊云-88-38" "亚马逊云-88-49"
], ],
"日本-东京": [ "日本-东京": [
"阿里云-88-38", "阿里云-88-49",
"亚马逊云-88-38" "亚马逊云-88-49"
], ],
"新加坡": [ "新加坡": [
"阿里云-88-38" "阿里云-88-49"
], ],
"澳大利亚-悉尼": [ "澳大利亚-悉尼": [
"阿里云-88-38", "阿里云-88-49",
"亚马逊云-68-38" "亚马逊云-68-49"
], ],
"马来西亚-吉隆坡": [ "马来西亚-吉隆坡": [
"阿里云-88-38" "阿里云-88-49"
], ],
"印度尼西亚-雅加达": [ "印度尼西亚-雅加达": [
"阿里云-68-38" "阿里云-68-49"
], ],
"孟买": [ "孟买": [
"阿里云-68-38" "阿里云-68-49"
], ],
"加拿大": [ "加拿大": [
"亚马逊云-68-38" "亚马逊云-68-49"
], ],
"巴西-圣保罗": [ "巴西-圣保罗": [
"亚马逊云-68-38" "亚马逊云-68-49"
], ],
"迪拜": [ "迪拜": [
"阿里云-88-38" "阿里云-88-49"
], ],
"本地": [ "本地": [
"本地ip-0-0" "本地ip-0-0"
] ]
}, },
"supportedPlatForm": { "supportedPlatForm": {
"中国随机": { "中国随机": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -385,7 +373,6 @@ ...@@ -385,7 +373,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"香港": { "香港": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -422,7 +409,6 @@ ...@@ -422,7 +409,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"美国随机": { "美国随机": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -561,7 +547,6 @@ ...@@ -561,7 +547,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"英国-伦敦": { "英国-伦敦": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -666,7 +651,6 @@ ...@@ -666,7 +651,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"日本-东京": { "日本-东京": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -807,7 +791,6 @@ ...@@ -807,7 +791,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"孟买": { "孟买": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -826,7 +809,6 @@ ...@@ -826,7 +809,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"加拿大": { "加拿大": {
"亚马逊云": [ "亚马逊云": [
"亚马逊-1", "亚马逊-1",
...@@ -863,7 +845,6 @@ ...@@ -863,7 +845,6 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"迪拜": { "迪拜": {
"阿里云": [ "阿里云": [
"亚马逊-1", "亚马逊-1",
...@@ -882,24 +863,24 @@ ...@@ -882,24 +863,24 @@
"其他平台-0" "其他平台-0"
] ]
}, },
"本地": { "本地": {
"本地": [ "本地": [
"亚马逊-1", "亚马逊-1",
"ebay-1", "ebay-1",
"全球速卖通-1", "全球速卖通-1",
"Wish-1", "Wish-1",
"Shopee-1", "Shopee-1",
"Lazada-1", "Lazada-1",
"CDiscount-1", "CDiscount-1",
"Joom-1", "Joom-1",
"Vova-1", "Vova-1",
"乐天-1", "乐天-1",
"Ozon-1", "Ozon-1",
"FactoryMarket-1", "FactoryMarket-1",
"PayPal-1", "PayPal-1",
"其他平台-1" "其他平台-1"
]} ]
}
}, },
"ipDurations": [ "ipDurations": [
"1周", "1周",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment