修改拉卡拉的加密解密

This commit is contained in:
Jack 2025-05-14 00:51:51 +08:00
parent fe3a25b352
commit d1c6630ef5
8 changed files with 165 additions and 62 deletions

View File

@ -217,6 +217,9 @@ public class ShopMchEntry implements Serializable {
@ApiModelProperty(value = "拉卡拉进件请求参数")
private String lkl_tk_reg_params;
@ApiModelProperty(value = "异步通知的请求参数(加密过)")
private String lkl_tk_reg_notify_req;
@ApiModelProperty(value = "拉卡拉进件成功返回的JSON数据")
private String lkl_tk_reg_resp;

View File

@ -21,8 +21,8 @@ public class JiebaUtils {
public static void main(String[] args) {
JiebaUtils jiebaUtils = new JiebaUtils();
String text = "中国工商银行桂平市光明支行";
List<String> words = jiebaUtils.segmentForSearch(text);
String text = "农行桂平";
List<String> words = jiebaUtils.segment(text);
System.out.println(words);
}

View File

@ -37,6 +37,15 @@ public class LklTkController extends BaseControllerImpl {
@Resource
private LklBanksService lklBanksService;
@ApiOperation(value = "解密拉卡拉进件返回的异步通知", notes = "解密拉卡拉进件返回的异步通知")
@RequestMapping(value = "/decode", method = RequestMethod.POST)
public String decryptLklTkData(@RequestParam(name = "data") String data,
@RequestParam(name = "key") String key) {
return lklTkService.decryptNotifyData(key, data);
}
@ApiOperation(value = "搜索国内银行(支行)分页列表", notes = "搜索国内银行(支行)分页列表,数据包含有效的收款结清行号")
@RequestMapping(value = "/bank/search", method = RequestMethod.POST)
public CommonResult searchLklBanksPageList(@RequestBody JSONObject paramsJSON) {

View File

@ -41,11 +41,16 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
@ -70,9 +75,6 @@ public class LklTkServiceImpl {
@Value("${lakala.tk.user_no}")
private String userNo;
@Value("${lakala.org_code}")
private String orgCode;
@Value("${lakala.tk.notify_pub_key_path}")
private String notifyPubKeyPath;
@ -102,6 +104,63 @@ public class LklTkServiceImpl {
@Autowired
private RedisService redisService;
/**
* 拉卡拉使用私钥加密数据
*/
public static String encryptNotifyData(String priKey, String data) {
ByteArrayOutputStream out = null;
try {
// pubKey 去掉 空格制表符\t换行符\n回车符\r
priKey = priKey.replaceAll("\\s+", "");
logger.debug("拉卡拉tk加密私钥{}", priKey);
logger.debug("拉卡拉tk待加密data数据{}", data);
// 解码私钥
byte[] keyBytes = Base64.getDecoder().decode(priKey);
// 生成私钥对象
PrivateKey privateKey = KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
// 初始化加密器
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
// 分段加密
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
out = new ByteArrayOutputStream();
for (int offset = 0; offset < dataBytes.length; offset += 117) {
int blockSize = Math.min(117, dataBytes.length - offset);
byte[] encryptedBlock = cipher.doFinal(dataBytes, offset, blockSize);
out.write(encryptedBlock);
}
// 编码为Base64字符串
String encryptDataStr = Base64.getEncoder().encodeToString(out.toByteArray());
logger.debug("拉卡拉tk数据加密结果{}", encryptDataStr);
return encryptDataStr;
} catch (Exception e) {
throw new RuntimeException("私钥加密失败", e);
} finally {
closeQuietly(out);
}
}
/**
* 安全关闭流
*/
private static void closeQuietly(ByteArrayOutputStream out) {
if (out != null) {
try {
out.close();
} catch (Exception e) {
// 忽略异常
}
}
}
/**
* 拉卡拉异步通知数据公钥解密
*
@ -110,14 +169,19 @@ public class LklTkServiceImpl {
* @return 解密字符串
*/
public String decryptNotifyData(String pubKey, String data) {
ByteArrayOutputStream out = null;
try {
logger.debug("拉卡拉tk解密公钥{}", pubKey);
logger.debug("拉卡拉tk待解密data数据{}", data);
// pubKey 去掉 空格制表符\t换行符\n回车符\r
pubKey = pubKey.replaceAll("\\s+", "");
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyBytes = decoder.decode(pubKey.getBytes());
byte[] dataBytes = decoder.decode(data.getBytes());
byte[] keyBytes = decoder.decode(pubKey.getBytes(StandardCharsets.UTF_8));
byte[] dataBytes = decoder.decode(data.getBytes(StandardCharsets.UTF_8));
Cipher cipher = Cipher.getInstance("RSA");
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes));
cipher.init(Cipher.DECRYPT_MODE, publicKey);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out = new ByteArrayOutputStream();
byte[] cache;
for (int i = 0, offset = 0, length = dataBytes.length; length - offset > 0; i++, offset = i * 128) {
if (length - offset > 128) {
@ -127,13 +191,23 @@ public class LklTkServiceImpl {
}
out.write(cache, 0, cache.length);
}
return out.toString();
String decodedDataStr = out.toString("UTF-8");
logger.debug("拉卡拉tk数据解密结果{}", decodedDataStr);
return decodedDataStr;
} catch (IllegalArgumentException e) {
logger.error("Base64 解码时出现非法参数异常: ", e.getMessage());
logger.error("Base64解码失败: {}", e.getMessage(), e);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
logger.error("RSA算法初始化失败: {}", e.getMessage(), e);
} catch (InvalidKeySpecException | InvalidKeyException e) {
logger.error("私钥格式或类型错误: {}", e.getMessage(), e);
} catch (BadPaddingException | IllegalBlockSizeException e) {
logger.error("解密数据块大小或填充错误: {}", e.getMessage(), e);
} catch (Exception e) {
// 捕获其他可能的异常 NoSuchAlgorithmExceptionNoSuchPaddingException
// InvalidKeySpecExceptionInvalidKeyExceptionBadPaddingException
logger.error("解密过程中出现异常: ", e.getMessage());
logger.error("解密过程中出现未知异常: {}", e.getMessage(), e);
} finally {
closeQuietly(out);
}
return null;
@ -400,7 +474,6 @@ public class LklTkServiceImpl {
formData.put("settleType", "D1"); //结算类型D0秒到D1次日结算
// formData.put("settlementType", "AUTOMATIC"); // 结算方式MANUAL:手动结算(结算至拉卡拉APP钱包),AUTOMATIC:自动结算到银行卡,REGULAR:定时结算仅企业商户支持
// 店铺省市区信息
Map<String, String> areaCode = getAreaCode(shopMchEntry.getStore_area(), false);
if (ObjectUtil.isNotEmpty(areaCode)) {
@ -422,7 +495,7 @@ public class LklTkServiceImpl {
}
// TODO 咨询拉卡拉清楚
// 费率和设备活动
JSONObject bizContent = new JSONObject();
bizContent.put("activityId", 687);
bizContent.put("termNum", "1");
@ -439,24 +512,26 @@ public class LklTkServiceImpl {
// 附件文件相关开始
JSONArray attachments = new JSONArray();
JSONObject ID_CARD_FRONT = updatePhoto(shopMchEntry.getIndividual_id_images(), "ID_CARD_FRONT", false);
if (ID_CARD_FRONT != null) {
attachments.put(ID_CARD_FRONT); // 身份证正面
}
if (isQy) {
JSONObject SETTLE_ID_CARD_FRONT = updatePhoto(shopMchEntry.getLegal_person_id_images(), "FR_ID_CARD_FRONT", false);
if (SETTLE_ID_CARD_FRONT != null) {
attachments.put(SETTLE_ID_CARD_FRONT); // 法人身份证正面
}
JSONObject ID_CARD_BEHIND = updatePhoto(shopMchEntry.getIndividual_id_images2(), "ID_CARD_BEHIND", false);
if (ID_CARD_BEHIND != null) {
attachments.put(ID_CARD_BEHIND); // 身份证国徽面
}
JSONObject SETTLE_ID_CARD_BEHIND = updatePhoto(shopMchEntry.getLegal_person_id_images2(), "FR_ID_CARD_BEHIND", false);
if (SETTLE_ID_CARD_BEHIND != null) {
attachments.put(SETTLE_ID_CARD_BEHIND); // 法人身份证国徽面
}
} else {
JSONObject ID_CARD_FRONT = updatePhoto(shopMchEntry.getIndividual_id_images(), "ID_CARD_FRONT", false);
if (ID_CARD_FRONT != null) {
attachments.put(ID_CARD_FRONT); // 身份证正面
}
JSONObject SETTLE_ID_CARD_FRONT = updatePhoto(shopMchEntry.getLegal_person_id_images(), "FR_ID_CARD_FRONT", false);
if (SETTLE_ID_CARD_FRONT != null) {
attachments.put(SETTLE_ID_CARD_FRONT); // 法人身份证正面
}
JSONObject SETTLE_ID_CARD_BEHIND = updatePhoto(shopMchEntry.getLegal_person_id_images2(), "FR_ID_CARD_BEHIND", false);
if (SETTLE_ID_CARD_BEHIND != null) {
attachments.put(SETTLE_ID_CARD_BEHIND); // 法人身份证国徽面
JSONObject ID_CARD_BEHIND = updatePhoto(shopMchEntry.getIndividual_id_images2(), "ID_CARD_BEHIND", false);
if (ID_CARD_BEHIND != null) {
attachments.put(ID_CARD_BEHIND); // 身份证国徽面
}
}
JSONObject BUSINESS_LICENCE = updatePhoto(shopMchEntry.getBiz_license_image(), "BUSINESS_LICENCE", false);
@ -486,18 +561,20 @@ public class LklTkServiceImpl {
logger.info("进件请求参数:{}", JSONUtil.toJsonStr(formData));
ResponseEntity<JSONObject> response = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, formData, JSONObject.class);
if (ObjectUtil.isEmpty(response) || response.getStatusCode() != HttpStatus.OK) {
String errMsg = "进件返回空或请求状态异常";
if (ObjectUtil.isNotEmpty(response.getBody()) && ObjectUtil.isNotEmpty(response.getBody().getStr("message"))) {
errMsg = response.getBody().getStr("message");
}
if (ObjectUtil.isEmpty(response)) {
return Pair.of(false, "进件失败:进件无返回值");
}
JSONObject respBody = response.getBody();
if (response.getStatusCode() != HttpStatus.OK && ObjectUtil.isNotEmpty(respBody)) {
String errMsg = respBody.getStr("message") == null ? "返回状态有误" : respBody.getStr("message");
return Pair.of(false, "进件失败:" + errMsg);
}
// 更改入驻记录的拉卡拉内部商户号和进件请求参数
String lklMerCupNo = response.getBody().getStr("merchantNo"); //拉卡拉内部商户号
String lklMerCupNo = respBody.getStr("merchantNo"); //拉卡拉内部商户号
// 表中的内部外部商户号暂时都传同一个内部商户号以便异步通知更改记录
Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchMobile, CommonConstant.Disable2, lklMerCupNo, lklMerCupNo, formData.toString());
Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchMobile, CommonConstant.Disable2, lklMerCupNo, lklMerCupNo, formData.toString(), respBody.toString());
if (!success) {
return Pair.of(false, "提交进件成功,但更新商户号失败!");
}
@ -518,7 +595,6 @@ public class LklTkServiceImpl {
*/
public JSONObject registrationMerchantNotify(HttpServletRequest request) {
logger.debug("拉卡拉进件异步通知开始");
JSONObject respData = new JSONObject();
// 解密请求参数
String requestBody = LakalaUtil.getBody(request);
@ -539,13 +615,13 @@ public class LklTkServiceImpl {
// 公钥解密出来的数据
String notifyPubKey = LakalaUtil.getResourceFile(notifyPubKeyPath);
logger.debug("解密公钥:{}", notifyPubKey);
String data = decryptNotifyData(notifyPubKey, srcData);
logger.debug("拉卡拉进件异步通知返回 data 数据:{}, 解密后的 data 数据:{}", srcData, data);
if (StrUtil.isBlank(data)) {
return new JSONObject().set("code", "500").set("message", "无法解密出 data 参数");
return new JSONObject().set("code", "500").set("message", "密文解密出错!");
}
logger.debug("拉卡拉进件异步通知data解密成功开始处理逻辑");
// 逻辑处理
JSONObject dataJSON = JSONUtil.parseObj(data);
if (dataJSON.isEmpty() || StrUtil.isBlank(dataJSON.getStr("externalCustomerNo"))) {
@ -557,7 +633,8 @@ public class LklTkServiceImpl {
String merInnerNo = dataJSON.getStr("customerNo"); //拉卡拉内部商户号
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
if (ObjectUtil.isEmpty(shopMchEntry)) {
return new JSONObject().set("code", "500").set("message", "商户入驻信息不存在");
logger.error("拉卡拉进件异步通知:返回的外部商户号:{} 入驻信息不存在!", merCupNo);
return new JSONObject().set("code", "500").set("message", "外部商户号:" + merCupNo + " 入驻信息不存在");
}
Boolean success = shopMchEntryService.updateMerchEntryLklAuditStatusByLklMerCupNo(merInnerNo, merCupNo, CommonConstant.Enable, data);

View File

@ -139,22 +139,23 @@ public interface ShopMchEntryService {
/**
* 更新商家入驻申请的拉卡拉商户号
*
* @param loginMobile
* @param lklAuditStatus
* @param loginMobile 商家注册的手机号
* @param lklAuditStatus 拉卡拉审核状态
* @param lklMerCupNo 拉卡拉银联商户号
* @param lklMerInnerNo 拉卡拉内部商户号
* @param lklTkRegParams
* @param lklTkRegParams 进件请求参数
* @param lklTkRegResp 进件返回的数据
* @return
*/
Boolean updateMerchEntryLklMerCupNo(String loginMobile, Integer lklAuditStatus, String lklMerCupNo, String lklMerInnerNo, String lklTkRegParams);
Boolean updateMerchEntryLklMerCupNo(String loginMobile, Integer lklAuditStatus, String lklMerCupNo, String lklMerInnerNo, String lklTkRegParams, String lklTkRegResp);
/**
* 更新商家入驻申请的拉卡拉审核状态和响应数据
*
* @param lklMerCupNo
* @param lklInnerMerNo
* @param lklAuditStatus
* @param lklTkRegResp
* @param lklMerCupNo 拉卡拉银联商户号
* @param lklInnerMerNo 拉卡拉内部商户号
* @param lklAuditStatus 拉卡拉审核状态
* @param lklTkRegResp 进件返回的数据
* @return
*/
Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklMerCupNo, String lklInnerMerNo, Integer lklAuditStatus, String lklTkRegResp);

View File

@ -411,6 +411,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
ShopMchEntry record = recordList.get(0);
// 审核意见空值返回"[]"
if (StrUtil.isBlank(record.getApproval_invalid_col())) {
record.setApproval_invalid_col("[]");
}
// 试试更新入驻表的合同下载地址和合同签署状态
updateMerchEntrySignedStatusAndContractDownloadUrl(record);
@ -676,7 +680,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
QueryWrapper<ShopMchEntry> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mer_cup_no", merCupNo).eq("status", CommonConstant.Enable).orderByAsc("id");
queryWrapper.eq("lkl_mer_cup_no", merCupNo).eq("status", CommonConstant.Enable).orderByAsc("id");
List<ShopMchEntry> recordList = list(queryWrapper);
if (CollectionUtil.isEmpty(recordList)) {
return null;
@ -732,7 +736,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
@Override
public Boolean updateMerchEntryLklMerCupNo(String loginMobile, Integer lklAuditStatus, String lklMerCupNo, String lklMerInnerNo, String lklTkRegParams) {
public Boolean updateMerchEntryLklMerCupNo(String loginMobile, Integer lklAuditStatus, String lklMerCupNo, String lklMerInnerNo, String lklTkRegParams, String lklTkRegResp) {
if (StrUtil.isBlank(loginMobile) && StrUtil.isBlank(lklMerCupNo)) {
return false;
}
@ -742,6 +746,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
if (ObjectUtil.isNotEmpty(lklAuditStatus)) {
updateWrapper.set("lkl_tk_audit_status", lklAuditStatus);
}
if (StrUtil.isNotBlank(lklMerCupNo)) {
updateWrapper.set("lkl_mer_cup_no", lklMerCupNo); // 银联商户号
}
@ -753,6 +758,14 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
if (StrUtil.isNotBlank(lklTkRegParams)) {
updateWrapper.set("lkl_tk_reg_params", lklTkRegParams);
}
if (StrUtil.isNotBlank(lklTkRegResp)) {
updateWrapper.set("lkl_tk_reg_resp", lklTkRegResp);
}
updateWrapper.set("approval_remark", "拉卡拉进件准备进入审核");
updateWrapper.set("approval_invalid_col", "[]");
return update(updateWrapper);
}
@ -762,11 +775,11 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
* @param lklInnerMerNo
* @param lklMerCupNo
* @param lklAuditStatus
* @param lklTkRegResp
* @param lklTkRegNotifyReq
* @return
*/
@Override
public Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklInnerMerNo, String lklMerCupNo, Integer lklAuditStatus, String lklTkRegResp) {
public Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklInnerMerNo, String lklMerCupNo, Integer lklAuditStatus, String lklTkRegNotifyReq) {
if (StrUtil.isBlank(lklMerCupNo)) {
return false;
}
@ -779,12 +792,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
// 商家入驻审核正式通过
updateWrapper.set("approval_status", CommonConstant.MCH_APPR_STA_PASS);
if (StrUtil.isNotBlank(lklMerCupNo)) {
updateWrapper.set("lkl_mer_cup_no", lklMerCupNo);
}
if (StrUtil.isNotBlank(lklTkRegResp)) {
updateWrapper.set("lkl_tk_reg_resp", lklTkRegResp);
if (StrUtil.isNotBlank(lklTkRegNotifyReq)) {
updateWrapper.set("lkl_tk_reg_notify_req", lklTkRegNotifyReq);
}
return update(updateWrapper);

View File

@ -1 +1 @@
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALKb2r7+J9aS9/aiDblUUlkMfU6XdIasmEm/GWVOAoIS+CGV+qItHrZ2uIxbdHGlQY0HBGGnPYNUDGipzQtgrEpzWFXvBkmO1tVLdUE5ZuQ6/6pzFgGJTOi9+ujSKE4hbPbTJ4y+/1qqVLypSV51j7m2QZREns8biKzuxKNRzDZFAgMBAAECgYAXLWtq+n8/9I1x92CRirQu8xR1tOi9qzsN4tsQTtm7eGuzrAs8rV89bVWQfTO0pa3Gd8ElTPcKCkeb82D014Qz4z7sLz3reNeYXay8PbCCegQxUn7xzykwckziydKw4cCBZQkmyCYtUZcyf+C2Z+0dX6dTO3Z7+/se0ndJleAbFwJBAO9omFP3+lxxXQgyv99+IJTRFp+xWZnfjWREU8aZQXy+QU1LYCxMafpaIJMOu4qwo1XwfLKelAuLc2kLQMhrEkcCQQC+/Jie67sp744bw2dBWo8LrghvIaPxkH9Sgkce3qHUPx4cK+tF/GtfujB4kKDhpQb4nEJtLhPEBjslL0bWkc0TAkAoRHBylx/+EncyXM7W+XDjdvOWMo8+iVJPzgpFOhvAroNvS8FGUif1GtmlwnGa1zDx0Hw40uFVu8PSpDjmPNQbAkEAsHBpiv/aVB6kmY+HF8BSwIaR8iEQ9Tz58z6595HTzWJWLc6BN5G/nJtE5k0u4+byrsClOXpE9maPQ4YOmnHuEwJAIEYvcN2Ju3on5wglbH2b9889zzg1P9z/1GbFPpi2kZeOZre2HQfojoU686oGBdvDe0BK6+jgir1hzwfJBB7fvQ==
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJDy8KWN4t65ifbOrCx+oChGorxzTVzh5RCeOCSS/0LJ57Qoc8BZ+xLyphtITtHtcIRY39cYFmSfjTLnNMV/Y+FC47EeBbDKiiIKg06o3/X+/sW+J9FNQs+6H7L15o9j1P0P0h8bo/cs3T88m9r57JMr3Vb3P/iTE4+6XT4HHRXvAgMBAAECgYAeZCGaxKYVxtcrfWfSKHaSG0VRt+c3m1F464Of/4Yvzb+cIYMriHJBJck4HTARifQ2e5/rLGy9ikqDqsCAzFX3e0/OG9wvvyodCoWYwVy37Zus5HqmYyndhdQGpTvw8lNVA90iOU5q5z8DxKc9iuiPLW0MCpgvQ6Xjsv/vBN3KqQJBAMTODXlM8kfsRaSs5YzSyamrcxruD3x0+vrHtkyR9e5Q+KWu1WcsFeRcRRXwtJYg8+9KiRB/fFOKRCowhzKYciUCQQC8i/18QEAPL3jczJsYe/Zt9lRK9qJjwXdgsPAsm5iwsv8oPUtWEykI+ct89twzbdXJYK4M1AM6d0qwit8rK+mDAkEAhlNJWQCO4U4/no0vxDVe1UKjNr9DrKO/ZgmHwK1jGT0E6TjyiQ/LBWmA8d+vskRdmnbaJHuPJQnbSpyCuqLYTQJBAIv3dC6n16YuPI/UyBIN/Cs3YO3hVz2soj1CPJkwzNHnnyk1D1cPlDfYj+ntrBv1nm4G+k4FmXvukKCsBu2ahJcCQBMBld8cpapoiou+oCeMay+W1W8kxsvwI4pW602FCecE2XJwWjvc/eht0D3j5F8wIvVxlzvX9lkZ5GYpEQBsIuw=

View File

@ -1 +1 @@
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCym9q+/ifWkvf2og25VFJZDH1Ol3SGrJhJvxllTgKCEvghlfqiLR62driMW3RxpUGNBwRhpz2DVAxoqc0LYKxKc1hV7wZJjtbVS3VBOWbkOv+qcxYBiUzovfro0ihOIWz20yeMvv9aqlS8qUledY+5tkGURJ7PG4is7sSjUcw2RQIDAQAB
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQ8vCljeLeuYn2zqwsfqAoRqK8c01c4eUQnjgkkv9Cyee0KHPAWfsS8qYbSE7R7XCEWN/XGBZkn40y5zTFf2PhQuOxHgWwyooiCoNOqN/1/v7FvifRTULPuh+y9eaPY9T9D9IfG6P3LN0/PJva+eyTK91W9z/4kxOPul0+Bx0V7wIDAQAB