export merchant list to excel.

qcloud scf impl
master
yixian 5 years ago
parent 3c33f9688b
commit 21ced08f55

@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>manage</artifactId>
<version>1.1.11</version>
<version>1.1.12</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

@ -39,6 +39,8 @@ public interface ClientManager {
JSONObject listClients(JSONObject manager, PartnerQuery query);
void exportClients(JSONObject manager,PartnerQuery query,HttpServletResponse resp);
JSONObject listClientsByApp(JSONObject manager, AppMerchantBean query);
List<JSONObject> listPartners(JSONObject manager, PartnerQuery query);

@ -40,6 +40,7 @@ import au.com.royalpay.payment.manage.permission.utils.OrgCheckUtils;
import au.com.royalpay.payment.manage.signin.beans.TodoNotice;
import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider;
import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.manage.support.serverless.ServerlessFunctionTrigger;
import au.com.royalpay.payment.manage.support.sms.SmsSender;
import au.com.royalpay.payment.manage.system.core.ClientContractService;
import au.com.royalpay.payment.manage.system.core.MailGunService;
@ -281,6 +282,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
@Resource
private CommonSubMerchantIdMapper commonSubMerchantIdMapper;
@Resource
private ServerlessFunctionTrigger serverlessFunctionTrigger;
@Resource
private Locker locker;
@Resource
private MongoTemplate mongoTemplate;
@ -487,6 +490,39 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
@Override
public JSONObject listClients(JSONObject manager, PartnerQuery query) {
JSONObject params = prepareListClientsParameter(manager, query);
PageList<JSONObject> partners = clientMapper.listPartners(params,
new PageBounds(query.getPage(), query.getLimit(), Order.formString("is_valid.desc,-approve_time.asc,create_time.desc")));
int authDays = PlatformEnvironment.getEnv().authDays();// 快速自助开通申请有效期
for (JSONObject partner : partners) {
String subMerchantId = partner.getString("sub_merchant_id");
if (subMerchantId != null) {
partner.put("temp_sub_merchant", checkSubMerchantIdInCommonPool(subMerchantId));
}
if (partner.getIntValue("approve_result") == 2) {
partner.put("expiry_time", DateUtils.addDays(partner.getDate("approve_time"), authDays));
partner.put("pass_timeout", DateUtils.addDays(partner.getDate("approve_time"), authDays).compareTo(new Date()) < 0);
}
}
return PageListUtils.buildPageListResult(partners);
}
@Override
public void exportClients(JSONObject manager, PartnerQuery query, HttpServletResponse resp) {
JSONObject params = prepareListClientsParameter(manager, query);
JSONObject retResp = serverlessFunctionTrigger.triggerFunction("export_merchants", params);
String contentB64 = retResp.getString("content");
resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
resp.setHeader("Content-Disposition", "attachment; filename=merchants.xlsx");
try (OutputStream out = resp.getOutputStream()) {
IOUtils.write(Base64.decodeBase64(contentB64), out);
out.flush();
} catch (IOException e) {
throw new ServerErrorException(e);
}
}
private JSONObject prepareListClientsParameter(JSONObject manager, PartnerQuery query) {
JSONObject params = query.toJsonParam();
if (params.getString("org_id") != null) {
if (params.getString("org_ids") == null) {
@ -549,20 +585,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
params.put("temp_mch_id", tempSubMchId);
params.put("temp_mch_id_source", tempSubMchSource);
}
PageList<JSONObject> partners = clientMapper.listPartners(params,
new PageBounds(query.getPage(), query.getLimit(), Order.formString("is_valid.desc,-approve_time.asc,create_time.desc")));
int authDays = PlatformEnvironment.getEnv().authDays();// 快速自助开通申请有效期
for (JSONObject partner : partners) {
String subMerchantId = partner.getString("sub_merchant_id");
if (subMerchantId != null) {
partner.put("temp_sub_merchant", checkSubMerchantIdInCommonPool(subMerchantId));
}
if (partner.getIntValue("approve_result") == 2) {
partner.put("expiry_time", DateUtils.addDays(partner.getDate("approve_time"), authDays));
partner.put("pass_timeout", DateUtils.addDays(partner.getDate("approve_time"), authDays).compareTo(new Date()) < 0);
}
}
return PageListUtils.buildPageListResult(partners);
return params;
}
@Override
@ -5167,6 +5190,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}
});
}
private TemplateMessage initSendTestPasswordTemplate(String wxopenid, String templateId) {
TemplateMessage msg = new TemplateMessage(wxopenid, templateId, PlatformEnvironment.getEnv().concatUrl("testMerchantPassword"));
msg.put("first", "系统测试商户账户已重置", "#000000");

@ -43,6 +43,11 @@ public class PartnerManageController {
return clientManager.listClients(manager, query);
}
@ManagerMapping(value = "/exporting_excel", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.FINANCIAL_STAFF})
public void exportClientsExcel(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, PartnerQuery query, HttpServletResponse resp) {
clientManager.exportClients(manager, query, resp);
}
@RequestMapping(value = "/list", method = RequestMethod.GET)
@RequireManager(role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.DIRECTOR})
public List<JSONObject> lisPartners(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, PartnerQuery query) {
@ -283,6 +288,7 @@ public class PartnerManageController {
/**
*
*
* @param clientMoniker
* @param pass
* @param manager
@ -697,6 +703,7 @@ public class PartnerManageController {
public List<JSONObject> getClientSubMerchantIdLogs(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.getClientSubMerchantIdLogs(clientMoniker, manager);
}
@ManagerMapping(value = "/unsub/{clientMoniker}", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR})
public void addSub(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.addSub(clientMoniker, manager);
@ -777,6 +784,7 @@ public class PartnerManageController {
/**
*
*
* @param clientMoniker
* @param channelKey
* @throws IOException

@ -0,0 +1,11 @@
package au.com.royalpay.payment.manage.support.serverless;
import com.alibaba.fastjson.JSONObject;
/**
* Create by davep at 2019-08-08 15:56
*/
public interface ServerlessFunctionTrigger {
JSONObject triggerFunction(String function,JSONObject params);
}

@ -0,0 +1,63 @@
package au.com.royalpay.payment.manage.support.serverless.qcloud;
import au.com.royalpay.payment.manage.support.serverless.ServerlessFunctionTrigger;
import au.com.royalpay.payment.manage.support.serverless.qcloud.support.ServerLessFunctionInvokeRequest;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
/**
* Create by davep at 2019-08-12 9:31
*/
@Service
public class QCloudServerlessTrigger implements ServerlessFunctionTrigger {
private Logger logger = LoggerFactory.getLogger(getClass());
private RestTemplate restTemplate;
private String secretId;
private String secretKey;
private String region;
public QCloudServerlessTrigger(@Value("${qcloud.secret-id}") String secretId,
@Value("${qcloud.secret-key}") String secretKey,
@Value("${qcloud.scf.region}") String region) {
this.secretId = secretId;
this.secretKey = secretKey;
this.region = region;
this.restTemplate = new RestTemplateBuilder()
.messageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8))
.build();
}
@Override
public JSONObject triggerFunction(String function, JSONObject params) {
ServerLessFunctionInvokeRequest request = new ServerLessFunctionInvokeRequest(secretId, secretKey, region, function, params);
ResponseEntity<String> resp = restTemplate.exchange(request.request(), String.class);
JSONObject data = JSON.parseObject(resp.getBody());
JSONObject response = data.getJSONObject("Response");
String requestId = response.getString("RequestId");
JSONObject result = response.getJSONObject("Result");
int invokeResult = result.getIntValue("InvokeResult");
if (invokeResult != 0) {
String errMsg = result.getString("ErrMsg");
logger.error("Invoking function [{}] failed,request id={},invoke result={},errMsg={}", function, requestId, invokeResult, errMsg);
throw new ServerErrorException("Invoke function " + function + " failed:[" + errMsg + "]");
} else {
String retMsg = result.getString("RetMsg");
return StringUtils.isNotEmpty(retMsg) ? JSON.parseObject(retMsg) : null;
}
}
}

@ -0,0 +1,135 @@
package au.com.royalpay.payment.manage.support.serverless.qcloud.support;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Create by davep at 2019-08-12 15:06
*/
public abstract class QCloudV3Request {
private static Logger logger = LoggerFactory.getLogger(QCloudV3Request.class);
private static final String ALGORITHM = "TC3-HMAC-SHA256";
private String secretId;
private String secretKey;
private String region;
private MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
public QCloudV3Request(String secretId, String secretKey, String region) {
this.secretId = secretId;
this.secretKey = secretKey;
this.region = region;
headers.add("host", host());
headers.add("content-type", contentType());
}
protected abstract String host();
protected abstract String uri();
protected abstract HttpMethod method();
protected abstract String action();
protected abstract String version();
protected abstract String contentType();
protected abstract String requestPayload();
protected abstract String queryStringParams();
protected String service() {
return StringUtils.substringBefore(host(), ".");
}
public void setHeader(String name, String value) {
headers.add(name, value);
}
public RequestEntity<String> request() {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl("https://" + host() + uri());
String queryStr = queryStringParams();
if (StringUtils.isNotEmpty(queryStr)) {
uriBuilder = uriBuilder.query(queryStr);
}
URI url = uriBuilder.build(false).toUri();
RequestEntity.BodyBuilder builder = RequestEntity.method(method(), url);
MultiValueMap<String, String> signHeaders = buildSignature();
for (Map.Entry<String, List<String>> entry : signHeaders.entrySet()) {
builder = builder.header(entry.getKey(), entry.getValue().toArray(new String[0]));
}
return builder.body(requestPayload());
}
private MultiValueMap<String, String> buildSignature() {
String timestamp = System.currentTimeMillis() / 1000 + "";
String date = DateTime.now(DateTimeZone.UTC).toString("yyyy-MM-dd");
// ************* 步骤 1拼接规范请求串 *************
String httpRequestMethod = method().name();
String canonicalUri = uri();
String canonicalQueryString = queryStringParams();
String canonicalHeaders = headers.entrySet().stream()
.flatMap(nameEntry -> nameEntry.getValue().stream()
.map(v -> nameEntry.getKey().toLowerCase() + ":" + v + "\n"))
.sorted()
.collect(Collectors.joining());
String signedHeaders = headers.keySet().stream().map(String::toLowerCase).sorted().collect(Collectors.joining(";"));
String hashedRequestPayload = DigestUtils.sha256Hex(requestPayload());
String canonicalRequest = String.join("\n", httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders, hashedRequestPayload);
logger.info("request:\n{}", canonicalRequest);
// ************* 步骤 2拼接待签名字符串 *************
String credentialScope = date + "/" + service() + "/tc3_request";
String hashedCanonicalRequest = DigestUtils.sha256Hex(canonicalRequest.getBytes(StandardCharsets.UTF_8));
String stringToSign = String.join("\n", ALGORITHM, timestamp, credentialScope, hashedCanonicalRequest);
logger.info("to sign:\n{}", stringToSign);
// ************* 步骤 3计算签名 *************
byte[] secretDate = sign256(("TC3" + secretKey).getBytes(StandardCharsets.UTF_8), date);
byte[] secretService = sign256(secretDate, service());
byte[] secretSigning = sign256(secretService, "tc3_request");
String signature = Hex.encodeHexString(sign256(secretSigning, stringToSign)).toLowerCase();
String authorization = String.format("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
ALGORITHM, secretId, credentialScope, signedHeaders, signature);
MultiValueMap<String, String> signHeaders = new LinkedMultiValueMap<>(headers);
signHeaders.set("Authorization", authorization);
signHeaders.set("X-TC-Action", action());
signHeaders.set("X-TC-Timestamp", timestamp);
signHeaders.set("X-TC-Version", version());
signHeaders.set("X-TC-Region", region);
return signHeaders;
}
private static byte[] sign256(byte[] key, String msg) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
logger.error(e.getMessage(), e);
throw new ServerErrorException(e);
}
}
}

@ -0,0 +1,62 @@
package au.com.royalpay.payment.manage.support.serverless.qcloud.support;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpMethod;
import org.springframework.util.MimeTypeUtils;
/**
* Create by davep at 2019-08-12 17:13
*/
public class ServerLessFunctionInvokeRequest extends QCloudV3Request {
private final String functionName;
private final JSONObject clientContext;
public ServerLessFunctionInvokeRequest(String secretId, String secretKey, String region, String functionName, JSONObject clientContext) {
super(secretId, secretKey, region);
this.functionName = functionName;
this.clientContext = clientContext == null ? new JSONObject() : clientContext;
}
@Override
protected String host() {
return "scf.tencentcloudapi.com";
}
@Override
protected String uri() {
return "/";
}
@Override
protected HttpMethod method() {
return HttpMethod.POST;
}
@Override
protected String action() {
return "Invoke";
}
@Override
protected String version() {
return "2018-04-16";
}
@Override
protected String contentType() {
return MimeTypeUtils.APPLICATION_JSON_VALUE;
}
@Override
protected String requestPayload() {
JSONObject data = new JSONObject();
data.put("FunctionName", functionName);
data.put("ClientContext", clientContext.toJSONString());
return data.toJSONString();
}
@Override
protected String queryStringParams() {
return "";
}
}

@ -144,3 +144,6 @@ app.hanyin-secure.sftp-port=28480
app.hanyin-secure.sftp-username=royalpay
app.hanyin-secure.sftp-pwd=royalpay
qcloud.secret-id=AKIDlHdjgWzZliPvBauZFfrnW0MaZOyHdTPz
qcloud.secret-key=YswoQDsIZfWEqEAEvMXS8Yic84lFn9Jp
qcloud.scf.region=ap-hongkong

@ -0,0 +1,81 @@
package au.com.royalpay.payment.manage.valid;
import au.com.royalpay.payment.manage.support.serverless.qcloud.support.ServerLessFunctionInvokeRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.Base64;
import org.junit.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Create by davep at 2019-08-08 16:21
*/
public class QCloudSignTest {
private String function = "export_merchants";
private String region = "ap-hongkong";
private String secretId = "AKIDlHdjgWzZliPvBauZFfrnW0MaZOyHdTPz";
private String secretKey = "YswoQDsIZfWEqEAEvMXS8Yic84lFn9Jp";
@Test
public void printUrl() throws NoSuchAlgorithmException, InvalidKeyException {
String host = "scf.tencentcloudapi.com/";
String method = "GET";
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put("Action", "Invoke");
paramsMap.put("Version", "2018-04-16");
paramsMap.put("Region", region);
paramsMap.put("FunctionName", function);
paramsMap.put("ClientContext", "{\"client_moniker\":\"PINE\"}");
paramsMap.put("Nonce", "" + RandomUtils.nextInt(0, 999999));
paramsMap.put("Timestamp", "" + System.currentTimeMillis() / 1000);
paramsMap.put("SignatureMethod", "HmacSHA256");
paramsMap.put("SecretId", secretId);
String[] params = paramsMap.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toArray(String[]::new);
Arrays.sort(params);
String base = method + host + "?" + StringUtils.join(params, "&");
String key = secretKey;
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
sha256HMAC.init(secretKey);
byte[] finalBytes = sha256HMAC.doFinal(base.getBytes());
String sign = Base64.encodeBase64String(finalBytes);
paramsMap.put("Signature", sign);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://" + host);
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
System.out.println(builder.build(false).encode().toUriString());
}
@Test
public void v3Test() {
RestTemplate restTemplate = new RestTemplateBuilder()
.messageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8))
.build();
JSONObject params = new JSONObject();
params.put("client_moniker", "PINE");
ServerLessFunctionInvokeRequest request = new ServerLessFunctionInvokeRequest(secretId, secretKey, region, function, params);
ResponseEntity<String> resp = restTemplate.exchange(request.request(), String.class);
System.out.println(resp.getBody());
}
}
Loading…
Cancel
Save