Commit 5513f075 authored by 黎博's avatar 黎博

微信和支付宝与支付中心对账

parent 839d5af5
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.0</version> <version>3.6</version>
</dependency> </dependency>
<!--mybatis-plus--> <!--mybatis-plus-->
...@@ -177,6 +177,23 @@ ...@@ -177,6 +177,23 @@
<artifactId>mongo-java-driver</artifactId> <artifactId>mongo-java-driver</artifactId>
<version>3.12.10</version> <version>3.12.10</version>
</dependency> </dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.30.ALL</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.20</version>
</dependency>
</dependencies> </dependencies>
......
package cn.qg.holmes.entity.reconciliation;
import lombok.Data;
/**
* 支付宝支付账单相关实体类
* @author libo
* 2022-02-22
*/
@Data
public class AliPayBillData {
/**
* 交易时间
*/
private String tradeTime;
/**
* 支付宝交易号
*/
private String aliPayTradeNo;
/**
* 商户订单号
*/
private String merchantOrderNo;
/**
* 业务类型
*/
private String tradeType;
/**
* 订单金额
*/
private String orderAmount;
/**
* 商家实收
*/
private String merchantReceiveAmount;
/**
* 退款批次号/请求号,仅业务类型是退款时有值
*/
private String refundOrderNo;
}
package cn.qg.holmes.entity.reconciliation;
import lombok.Data;
/**
* 微信支付账单相关数据实体类
* @author libo
* 2022-02-21
*/
@Data
public class WxPayBillData {
/**
* 交易时间
*/
private String tradeTime;
/**
* 微信订单号
*/
private String wxOrderNo;
/**
* 商户订单号
*/
private String merchantOrderNo;
/**
* 交易类型
*/
private String tradeType;
/**
* 交易状态
*/
private String tradeStatus;
/**
* 订单金额
*/
private String orderAmount;
/**
* 微信退款单号
*/
private String wxRefundOrderNo;
/**
* 商户退款单号
*/
private String merchantRefundOrderNo;
/**
* 退款类型
*/
private String refundType;
/**
* 退款状态
*/
private String refundStatus;
/**
* 退款金额
*/
private String refundAmount;
}
package cn.qg.holmes.service.reconciliation;
import cn.qg.holmes.entity.reconciliation.WxPayBillData;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.hash.Hashing;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.util.*;
import static com.google.common.base.Charsets.UTF_8;
/**
* 微信支付账单服务
*
* @author libo
* 2022-02-21
*/
@Slf4j
@Component
public class WxPayBillService {
private final String WX_API_KEY = "77f7565be7d8992ab882d4dc31271c71";
private final String WX_BILL_DOWNLOAD_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";
private final String WX_FUND_FLOW_DOWNLOAD_URL = "https://api.mch.weixin.qq.com/pay/downloadfundflow";
/**
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6
* 下载微信支付交易账单
*
* @param billDate 下载对账单的日期,格式:20140603
* @param billType ALL(默认值),返回当日所有订单信息(不含充值退款订单)SUCCESS,返回当日成功支付的订单(不含充值退款订单), REFUND,返回当日退款订单(不含充值退款订单,RECHARGE_REFUND,返回当日充值退款订单
* @return
*/
public String downloadTradeBillFile(String billDate, String billType) {
log.info("开始下载微信支付交易账单,账单日期:{}, 账单类型:{}", billDate, billType);
String randomString = UUID.randomUUID().toString().replace("-", "");
TreeMap<String, Object> treeMap = new TreeMap<>();
treeMap.put("appid", "wx75d5a207551d0b4d");
treeMap.put("mch_id", "1604055791");
treeMap.put("nonce_str", randomString);
treeMap.put("bill_date", billDate);
treeMap.put("bill_type", billType);
treeMap.put("sign", md5Sign(treeMap));
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(WX_BILL_DOWNLOAD_URL);
CloseableHttpResponse response = null;
try {
httpPost.setHeader("Content-type", "text/xml");
String params = mapToXml(treeMap);
HttpEntity entity = new StringEntity(params);
httpPost.setEntity(entity);
response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
return content;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
/**
* 解析微信交易账单
*
* @param content 微信交易账单内容
* @param billType 账单类型
* @return
*/
public List<WxPayBillData> parseTradeBill(String content, String billType) {
log.info("开始解析微信账单文件.");
if (StringUtils.isEmpty(content)) {
return null;
}
String[] tradeBillArray = content.split("\n");
List<WxPayBillData> wxTradeBillDataList = new ArrayList<>();
// 三种类型账单下载的文件格式不一样,分别处理
if (StringUtils.equals(billType, "ALL")) {
// 第一行为表头,最后两行为统计数据,均忽略
for (int i = 1; i < tradeBillArray.length - 2; i++) {
String[] dataArray = tradeBillArray[i].replace("`", "").split(",");
WxPayBillData wxTradeBillData = new WxPayBillData();
wxTradeBillData.setTradeTime(dataArray[0]);
wxTradeBillData.setWxOrderNo(dataArray[5]);
wxTradeBillData.setMerchantOrderNo(dataArray[6]);
wxTradeBillData.setTradeType(dataArray[8]);
wxTradeBillData.setTradeStatus(dataArray[9]);
wxTradeBillData.setOrderAmount(dataArray[24]);
wxTradeBillData.setWxRefundOrderNo(dataArray[14]);
wxTradeBillData.setMerchantRefundOrderNo(dataArray[15]);
wxTradeBillData.setRefundAmount(dataArray[16]);
wxTradeBillData.setRefundType(dataArray[18]);
wxTradeBillData.setRefundStatus(dataArray[19]);
wxTradeBillDataList.add(wxTradeBillData);
}
}
if (StringUtils.equals(billType, "SUCCESS")) {
for (int i = 1; i < tradeBillArray.length - 2; i++) {
String[] dataArray = tradeBillArray[i].replace("`", "").split(",");
WxPayBillData wxTradeBillData = new WxPayBillData();
wxTradeBillData.setTradeTime(dataArray[0]);
wxTradeBillData.setWxOrderNo(dataArray[5]);
wxTradeBillData.setMerchantOrderNo(dataArray[6]);
wxTradeBillData.setTradeType(dataArray[8]);
wxTradeBillData.setTradeStatus(dataArray[9]);
wxTradeBillData.setOrderAmount(dataArray[18]);
wxTradeBillDataList.add(wxTradeBillData);
}
}
if (StringUtils.equals(billType, "REFUND")) {
for (int i = 1; i < tradeBillArray.length - 2; i++) {
String[] dataArray = tradeBillArray[i].replace("`", "").split(",");
WxPayBillData wxTradeBillData = new WxPayBillData();
wxTradeBillData.setTradeTime(dataArray[0]);
wxTradeBillData.setWxOrderNo(dataArray[5]);
wxTradeBillData.setMerchantOrderNo(dataArray[6]);
wxTradeBillData.setTradeType(dataArray[8]);
wxTradeBillData.setTradeStatus(dataArray[9]);
wxTradeBillData.setWxRefundOrderNo(dataArray[16]);
wxTradeBillData.setMerchantRefundOrderNo(dataArray[17]);
wxTradeBillData.setRefundAmount(dataArray[18]);
wxTradeBillData.setRefundType(dataArray[20]);
wxTradeBillData.setRefundStatus(dataArray[21]);
wxTradeBillDataList.add(wxTradeBillData);
}
}
return wxTradeBillDataList;
}
/**
* md5签名
*
* @param value
* @return
*/
public String md5Sign(Object value) {
JSONObject jsonMap = JSON.parseObject(JSON.toJSONString(value));
TreeMap<String, Object> treeMap = new TreeMap<>(jsonMap);
String signStr = Joiner.on("&").withKeyValueSeparator("=").join(treeMap);
return Hashing.md5().newHasher()
.putString(signStr + "&key=" + WX_API_KEY, UTF_8)
.hash()
.toString()
.toUpperCase();
}
public String mapToXml(SortedMap<String, Object> sortedMap) {
StringBuffer sb = new StringBuffer("<xml>");
Iterator iterator = sortedMap.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
Object value = sortedMap.get(key);
sb.append("<" + key + ">");
sb.append(value);
sb.append("</" + key + ">");
}
sb.append("</xml>");
return sb.toString();
}
}
...@@ -6,7 +6,6 @@ import cn.qg.holmes.service.quality.DingRobotService; ...@@ -6,7 +6,6 @@ import cn.qg.holmes.service.quality.DingRobotService;
import cn.qg.holmes.service.quality.JiraBugPoolService; import cn.qg.holmes.service.quality.JiraBugPoolService;
import cn.qg.holmes.service.quality.JiraService; import cn.qg.holmes.service.quality.JiraService;
import cn.qg.holmes.utils.DingdingUtils; import cn.qg.holmes.utils.DingdingUtils;
import com.alibaba.fastjson.JSON;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -21,6 +20,7 @@ import java.util.List; ...@@ -21,6 +20,7 @@ import java.util.List;
/** /**
* JIRA BUG相关定时任务 * JIRA BUG相关定时任务
* @author libo
*/ */
@Component @Component
@Slf4j @Slf4j
...@@ -38,8 +38,8 @@ public class BugNotifyTask { ...@@ -38,8 +38,8 @@ public class BugNotifyTask {
@Value("${sjgd.ding.url}") @Value("${sjgd.ding.url}")
private String sjgdDingUrl; private String sjgdDingUrl;
@Value("${task.debug}") @Value("${scheduled.task.start}")
private String taskDebug; private String scheduledTaskStart;
/** /**
* 电商线上故障处理群钉钉机器人地址 * 电商线上故障处理群钉钉机器人地址
...@@ -59,7 +59,7 @@ public class BugNotifyTask { ...@@ -59,7 +59,7 @@ public class BugNotifyTask {
*/ */
// @Scheduled(cron = "0 0 19 * * ?") // @Scheduled(cron = "0 0 19 * * ?")
public void SJGDJiraIssueStatisticsTimedJob() throws Exception { public void SJGDJiraIssueStatisticsTimedJob() throws Exception {
if (taskDebug.equals("true")) { if (scheduledTaskStart.equals("true")) {
log.info("开始执行数据工单BUG统计定时任务!"); log.info("开始执行数据工单BUG统计定时任务!");
Iterable<Issue> issues = jiraService.getUnsolvedIssueListByProject("SJGD"); Iterable<Issue> issues = jiraService.getUnsolvedIssueListByProject("SJGD");
String markdownMsg = DingdingUtils.buildMarkdownMsgForUnsolvedIssueList(issues); String markdownMsg = DingdingUtils.buildMarkdownMsgForUnsolvedIssueList(issues);
...@@ -75,7 +75,7 @@ public class BugNotifyTask { ...@@ -75,7 +75,7 @@ public class BugNotifyTask {
*/ */
// @Scheduled(cron = "0 0 10-20 ? * MON-FRI") // @Scheduled(cron = "0 0 10-20 ? * MON-FRI")
public void cycleJiraBugPool() throws Exception { public void cycleJiraBugPool() throws Exception {
if (taskDebug.equals("true")) { if (scheduledTaskStart.equals("true")) {
log.info("开始执行jira bug pool定时任务!"); log.info("开始执行jira bug pool定时任务!");
QueryWrapper<JiraBugPool> jiraBugPoolQueryWrapper = new QueryWrapper<>(); QueryWrapper<JiraBugPool> jiraBugPoolQueryWrapper = new QueryWrapper<>();
jiraBugPoolQueryWrapper.eq("enable", 1); jiraBugPoolQueryWrapper.eq("enable", 1);
...@@ -124,7 +124,7 @@ public class BugNotifyTask { ...@@ -124,7 +124,7 @@ public class BugNotifyTask {
// @Scheduled(cron = "0 */1 * * * ?") // @Scheduled(cron = "0 */1 * * * ?")
@Scheduled(cron = "0 0 18 ? * MON-FRI") @Scheduled(cron = "0 0 18 ? * MON-FRI")
public void DailyCycleHandleJiraBugPool() { public void DailyCycleHandleJiraBugPool() {
if (taskDebug.equals("true")) { if (scheduledTaskStart.equals("true")) {
// 首先遍历ding_robot, 获取状态是进行中的项目 // 首先遍历ding_robot, 获取状态是进行中的项目
QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper<>(); QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper<>();
dingRobotQueryWrapper.eq("status", 1); dingRobotQueryWrapper.eq("status", 1);
...@@ -177,7 +177,7 @@ public class BugNotifyTask { ...@@ -177,7 +177,7 @@ public class BugNotifyTask {
// @Scheduled(cron = "0 */1 * * * ?") // @Scheduled(cron = "0 */1 * * * ?")
@Scheduled(cron = "0 0 18 ? * *") @Scheduled(cron = "0 0 18 ? * *")
public void prodBugDailyNotifyTask() throws Exception { public void prodBugDailyNotifyTask() throws Exception {
if (taskDebug.equals("true")) { if (scheduledTaskStart.equals("true")) {
Iterable<Issue> dsUnsolvedList = jiraService.getIssueListByJQL("project = YXMXS AND resolution = Unresolved ORDER BY priority DESC, created DESC"); Iterable<Issue> dsUnsolvedList = jiraService.getIssueListByJQL("project = YXMXS AND resolution = Unresolved ORDER BY priority DESC, created DESC");
Iterable<Issue> jrUnsolvedList = jiraService.getIssueListByJQL("project = YFGDZZ AND resolution = Unresolved ORDER BY priority DESC, created DESC"); Iterable<Issue> jrUnsolvedList = jiraService.getIssueListByJQL("project = YFGDZZ AND resolution = Unresolved ORDER BY priority DESC, created DESC");
DingdingUtils.sendToDingding(DingdingUtils.buildDailyProdBugNotifyMsg(dsUnsolvedList), dsProdDingUrl); DingdingUtils.sendToDingding(DingdingUtils.buildDailyProdBugNotifyMsg(dsUnsolvedList), dsProdDingUrl);
......
This diff is collapsed.
package cn.qg.holmes.utils;
import org.apache.commons.lang3.time.FastDateFormat;
import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
/**
* 日期格式化工具类
*/
public class DateUtils {
public static Date getCurrentTime() {
return new Date(System.currentTimeMillis());
}
public static String getCurrentDate(String pattern) {
LocalDate now = LocalDate.now();
return now.format(DateTimeFormatter.ofPattern(pattern));
}
public static String convertDate(Date date, String pattern) {
return FastDateFormat
.getInstance(pattern)
.format(date);
}
public static Date convertStr(String date, String pattern) throws ParseException {
return FastDateFormat
.getInstance(pattern)
.parse(date);
}
public static long betweenDays(Date dateBefore, Date dateAfter) {
return Duration.between(toLocalDate(dateBefore).atStartOfDay(), toLocalDate(dateAfter).atStartOfDay())
.toDays();
}
public static LocalDate toLocalDate(Date date) {
return date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
}
public static String formatLocalTime(LocalTime localTime, String pattern) {
return DateTimeFormatter.ofPattern(pattern).format(localTime);
}
public static String formatLocalDate(LocalDate localDate, String pattern) {
return DateTimeFormatter.ofPattern(pattern).format(localDate);
}
// 获得某天最小时间 2020-02-17 00:00:00
public static Date getStartOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
// 获得某天最大时间 2020-02-19 23:59:59
public static Date getEndOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
// 获取指定日期的前几天
public static Date getBeforeDay(Date date, int day) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_MONTH, day * -1);
return calendar.getTime();
}
// 获取指定日期的后几天
public static Date getAfterDay(Date date, int day) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(date.getTime());
c.add(Calendar.DATE, day);
return new Date(c.getTimeInMillis());
}
}
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQICARFv38DKhJ31odYtzGpDANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
YXNzIDIgUjEwHhcNMjAxMTE2MDcwMTMwWhcNMjIxMTE2MDcwMTMwWjCBjzELMAkGA1UEBhMCQ04x
KjAoBgNVBAoMIeWMl+S6rOmHj+WMlua0vuenkeaKgOaciemZkOWFrOWPuDEPMA0GA1UECwwGQWxp
cGF5MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZkOWFrOWPuC0y
MDg4OTMxOTU1NzA1MzIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm9LT+VzzI6Zy
r7ePg67m+6AB593Mpz9Pu3mdaYqhyN1MsW5p9l7Fjj/PSKJrCW7FzclCdDMVJrIMdopUMrscaHY8
ddncLA3+E0r5XK5+2lBmb35SNNlsKfVgnt122AymK5mkdar7rqOtQ1QrXM8NtlcY3UdZTUaPWbz5
0A/t2tlMoUSM9EANgqQbrT7wPIG+5bq6VWW2piVcyx+Qh0CLHLd9E3QSJKyYzYfJpLFjiQlSa8/S
aEHuBQTREyuO0/Kz/2Pxt5r7kkU80Yd0l4E1/oYPd3EhMbRpFNh79LxKjVtgxWq1hf2sdarvT9Ce
OftxnDn3yXTFXa9CEQqtByoANQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJKoZIhvcNAQEL
BQADggEBAEiC3Dzm+oayzvSJoZZA3jrxdRJhJ6pQQ1vGcCe1mNfR7XKA0r4ht4J4weTryF9tmUVw
6D+5UFdiA/2AfwOQ3rxmhc3TTN9xFDzm5koGfHFI9UV46PfBtugTUbgc+5HqsPPzcy6SvsQk3V17
/3ua+c/wM4Db9S7JX0Ug2kfFYsGZ/IxRQYmTiHDcD4FYUKjAep0uPbVu0/Nc5gR2OKiGwwr8MvDQ
dmozWdgJ42on5N7KkRNy0rRINQ9Z/QNMtQQ8GJB73rEbdty7q4psBsZ5Si2FuejNJSN4BuLybcM8
IZRSYtUFCmzX9QoKfUMQO215f6bxMK9GZFu0TyWTxlXjvr0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG
EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw
MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO
UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT
V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti
W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ
MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b
53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI
pDoiVhsLwg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0
MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV
BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j
aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk
rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2
xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp
dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6
vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl
YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1
Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H
DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98
SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG
PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe
9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC
AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90
tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy
nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf
tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq
JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3
IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW
05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41
T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI
kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop
PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N
1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y
jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02
77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi
kT9qhqn+lw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG
EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0
WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp
YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU
WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt
rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ
4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2
zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg
wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH
Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF
BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM
E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg
MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq
MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp
bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv
b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV
nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5
4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg
wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw
WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN
z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g
KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA
uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF
MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp
emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3
U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I
UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn
DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU
1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX
Yf4Zr0fJsGuv
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIErjCCA5agAwIBAgIQICARGDrIh1PZVJ5tAyihwzANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
YXNzIDEgUjEwHhcNMjAxMTE4MDkwOTE2WhcNMjIxMTE4MDkwOTE2WjB2MQswCQYDVQQGEwJDTjEq
MCgGA1UECgwh5YyX5Lqs6YeP5YyW5rS+56eR5oqA5pyJ6ZmQ5YWs5Y+4MQ8wDQYDVQQLDAZBbGlw
YXkxKjAoBgNVBAMMITIwODg5MzE5NTU3MDUzMjMtMjAyMTAwMjEwNjY0NDcxNDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBALeuAdr/HruBpjTxEmh5VYuCECJCigsb906iNb7rf1EC6KuH
EvJ65rBtxyHb3W6P/3Qw9NDLzqc0opAFt63jUxC1Lwvq2z/kGOnYZiDOxCWY8JFYTsiX3j/pHXx+
D1llDivHbzQGtfrSEpMVwz6ufoi40CJPvAcxyyOidEuxtZb9lpKYzColx+FFTb/xKXOfDYBfyMez
df9lm0zy6ybcd3jVT2bsMhE+B6OjjCWBOZSsUmuBAhZ2y5IJibzxrgHMVzdZ9rY2jmy2qQdmLOyy
HHnZQY6C+Al3EXo9SoL1p/6pBJ2V1Nxs55COBBsk4t+Jmg9DPI7wNqzMjMmQHwUHfwMCAwEAAaOC
ASkwggElMB8GA1UdIwQYMBaAFHEH4gRhFuTl8mXrMQ/J4PQ8mtWRMB0GA1UdDgQWBBQImTjGQ3Bx
PQVszP7T4OZ+am6YGTBABgNVHSAEOTA3MDUGB2CBHAFuAQEwKjAoBggrBgEFBQcCARYcaHR0cDov
L2NhLmFsaXBheS5jb20vY3BzLnBkZjAOBgNVHQ8BAf8EBAMCBsAwLwYDVR0fBCgwJjAkoCKgIIYe
aHR0cDovL2NhLmFsaXBheS5jb20vY3JsNDcuY3JsMGAGCCsGAQUFBwEBBFQwUjAoBggrBgEFBQcw
AoYcaHR0cDovL2NhLmFsaXBheS5jb20vY2E2LmNlcjAmBggrBgEFBQcwAYYaaHR0cDovL2NhLmFs
aXBheS5jb206ODM0MC8wDQYJKoZIhvcNAQELBQADggEBAAuKP7KQadec991A8SFAZsaIHIPFb5mb
Tb+shnzi71IeNsAnBWqhjKzBwEMAeyJt6z652pOE3zuzJ5XimPS5AUz8ZK91D9ViEuk03vBs1r2g
ZW5dEmqZwg0m2q7KXV8hNjzSKqlSyVojxjHwvdh6iHsKCtiMz0CRic6CkKMSTInP98g1lYjxsbL2
Vr1o22BvOtdr2sGeYFZbe8eNURyfmeiIPGcOwOwLURc0U32tm4MP+PqceW6jzRjjh7VCU0luOHWT
ZRnO4jWrhkF3E1Cqgg2OUWEdd2yAsbUuMbVb7Hm1HPNGOY5/V/D1AW3l4Obc+SffrPZKM/QJK3sq
VUPXWU8=
-----END CERTIFICATE-----
\ No newline at end of file
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