发布通告功能
This commit is contained in:
parent
194ec6d12d
commit
8cf3786d42
@ -25,7 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
<version>0.2.12</version>
|
||||
<version>0.2.17</version>
|
||||
</dependency>
|
||||
<!-- spring-boot-devtools -->
|
||||
<dependency>
|
||||
|
||||
@ -11,10 +11,15 @@ import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.member.domain.MemberOrder;
|
||||
import com.ruoyi.member.service.IMemberOrderService;
|
||||
import com.ruoyi.payConfig.WechatPayConfig;
|
||||
import com.ruoyi.payConfig.WechatPayRequest;
|
||||
import com.ruoyi.payConfig.WechatPayUrlEnum;
|
||||
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAPublicKeyConfig;
|
||||
|
||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
|
||||
import com.wechat.pay.java.service.payments.jsapi.model.*;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -34,8 +39,7 @@ import java.util.Map;
|
||||
public class PayApi {
|
||||
@Resource
|
||||
private WechatPayConfig wechatPayConfig;
|
||||
@Resource
|
||||
private WechatPayRequest wechatPayRequest;
|
||||
|
||||
@Autowired
|
||||
private IMemberOrderService memberOrderService;
|
||||
/**
|
||||
@ -45,41 +49,39 @@ public class PayApi {
|
||||
*/
|
||||
@ApiOperation(value = "统一下单-统一接口", notes = "统一下单-统一接口")
|
||||
@GetMapping("/prepayment")
|
||||
public Map<String,Object> transactions(String type, Long orderNo) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, IOException {
|
||||
public PrepayWithRequestPaymentResponse transactions(String type, String orderNo) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, IOException {
|
||||
LambdaQueryWrapper<MemberOrder> queryWrapper =new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(MemberOrder::getOrderNo,orderNo).last("limit 1");
|
||||
MemberOrder memberOrder = memberOrderService.getOne(queryWrapper);
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
// 统一参数封装
|
||||
Map<String, Object> params = new HashMap<>(8);
|
||||
params.put("appid", wechatPayConfig.getAppId());
|
||||
params.put("mchid", wechatPayConfig.getMchId());
|
||||
params.put("description", "开通会员");
|
||||
params.put("out_trade_no", orderNo.toString());
|
||||
params.put("notify_url", wechatPayConfig.getNotifyUrl());
|
||||
Map<String, Object> amountMap = new HashMap<>(4);
|
||||
BigDecimal goodsPrice = memberOrder.getGoodsPrice();
|
||||
// 金额单位为分
|
||||
amountMap.put("total", goodsPrice.multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP).intValue());
|
||||
//人民币
|
||||
amountMap.put("currency", "CNY");
|
||||
params.put("amount", amountMap);
|
||||
|
||||
// 场景信息
|
||||
Map<String, Object> sceneInfoMap = new HashMap<>(4);
|
||||
// 客户端IP
|
||||
sceneInfoMap.put("payer_client_ip", "127.0.0.1");
|
||||
// 商户端设备号(门店号或收银设备ID)
|
||||
sceneInfoMap.put("device_id", "127.0.0.1");
|
||||
// 除H5与JSAPI有特殊参数外,其他的支付方式都一样
|
||||
Map<String, Object> payerMap = new HashMap<>(4);
|
||||
payerMap.put("openid", user.getWxOpenId());
|
||||
params.put("payer", payerMap);
|
||||
params.put("scene_info", sceneInfoMap);
|
||||
String paramsStr = JSON.toJSONString(params);
|
||||
String resStr = wechatPayRequest.wechatHttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",paramsStr);
|
||||
Map<String, Object> resMap = JSONObject.parseObject(resStr, new TypeReference<Map<String, Object>>(){});
|
||||
return paySignMsg(resMap.get("prepay_id").toString(), wechatPayConfig.getAppId(),null);
|
||||
// 使用微信支付公钥的RSA配置
|
||||
Config config =
|
||||
new RSAPublicKeyConfig.Builder()
|
||||
.merchantId(wechatPayConfig.getMchId())
|
||||
.privateKeyFromPath(wechatPayConfig.getPrivateKeyPath())
|
||||
.publicKeyFromPath(wechatPayConfig.getPublicKeyPath())
|
||||
.publicKeyId(wechatPayConfig.getPublicKeyId())
|
||||
.merchantSerialNumber(wechatPayConfig.getSerialNo())
|
||||
.apiV3Key(wechatPayConfig.getApiV3Key())
|
||||
.build();
|
||||
// 构建service
|
||||
JsapiServiceExtension service = new JsapiServiceExtension .Builder().config(config).build();
|
||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||
PrepayRequest request = new PrepayRequest();
|
||||
Amount amount = new Amount();
|
||||
Payer payer = new Payer();
|
||||
amount.setTotal(100);
|
||||
payer.setOpenid(user.getWxOpenId());
|
||||
request.setAmount(amount);
|
||||
request.setAppid(wechatPayConfig.getAppId());
|
||||
request.setMchid(wechatPayConfig.getMchId());
|
||||
request.setDescription("开通会员");
|
||||
request.setNotifyUrl(wechatPayConfig.getNotifyUrl());
|
||||
request.setOutTradeNo(orderNo);
|
||||
request.setPayer(payer);
|
||||
// 调用下单方法,得到应答
|
||||
// response包含了调起支付所需的所有参数,可直接用于前端调起支付
|
||||
return service.prepayWithRequestPayment(request);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "支付回调", notes = "支付回调")
|
||||
@ -95,56 +97,13 @@ public class PayApi {
|
||||
JSONObject decryptDataObj = JSONObject.parseObject(decryptData, JSONObject.class);
|
||||
String orderNo = decryptDataObj.get("out_trade_no").toString();
|
||||
//调用业务系统
|
||||
memberOrderService.payCallback(orderNo);
|
||||
Map<String, String> res = new HashMap<>();
|
||||
res.put("code", "SUCCESS");
|
||||
res.put("message", "成功");
|
||||
return res;
|
||||
}
|
||||
|
||||
String buildMessage(String appId, String timestamp,String nonceStr,String prepay_id) {
|
||||
|
||||
return appId + "\n"
|
||||
+ timestamp + "\n"
|
||||
+ nonceStr + "\n"
|
||||
+ prepay_id + "\n";
|
||||
}
|
||||
|
||||
String sign(byte[] message,String privateKeyStr) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
|
||||
//签名方式
|
||||
Signature sign = Signature.getInstance("SHA256withRSA");
|
||||
//私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
|
||||
PrivateKey privateKey =null;
|
||||
if (StringUtils.isNotEmpty(privateKeyStr)){
|
||||
privateKey = PemUtil.loadPrivateKey(privateKeyStr);
|
||||
}else {
|
||||
privateKey = wechatPayConfig.getPrivateKey(wechatPayConfig.getKeyPemPath());
|
||||
}
|
||||
|
||||
sign.initSign(privateKey);
|
||||
sign.update(message);
|
||||
return Base64.getEncoder().encodeToString(sign.sign());
|
||||
}
|
||||
|
||||
private Map<String, Object> paySignMsg(String prepayId,String appId,String privateKeyStr) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
String timeStamp = timeMillis/1000+"";
|
||||
String nonceStr = timeMillis+"";
|
||||
String packageStr = "prepay_id="+prepayId;
|
||||
// 公共参数
|
||||
Map<String, Object> resMap = new HashMap<>();
|
||||
resMap.put("nonceStr",nonceStr);
|
||||
resMap.put("timeStamp",timeStamp);
|
||||
resMap.put("appId",appId);
|
||||
resMap.put("package", packageStr);
|
||||
// 使用字段appId、timeStamp、nonceStr、package进行签名
|
||||
//从下往上依次生成
|
||||
String message = buildMessage(appId, timeStamp, nonceStr, packageStr);
|
||||
//签名
|
||||
String paySign = sign(message.getBytes("utf-8"), privateKeyStr);
|
||||
resMap.put("paySign", paySign);
|
||||
resMap.put("signType", "RSA");
|
||||
return resMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -64,7 +64,9 @@ public class WechatPayConfig {
|
||||
/**
|
||||
* API 证书中的 key.pem
|
||||
*/
|
||||
private String keyPemPath;
|
||||
private String privateKeyPath;
|
||||
private String publicKeyPath;
|
||||
private String publicKeyId;
|
||||
|
||||
/**
|
||||
* 商户序列号
|
||||
@ -76,87 +78,5 @@ public class WechatPayConfig {
|
||||
*/
|
||||
private String baseUrl;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取商户的私钥文件
|
||||
* @param keyPemPath
|
||||
* @return
|
||||
*/
|
||||
public PrivateKey getPrivateKey(String keyPemPath){
|
||||
log.info("进入获取");
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(keyPemPath);
|
||||
if(inputStream==null){
|
||||
log.info("私钥文件不存在");
|
||||
throw new RuntimeException("私钥文件不存在");
|
||||
}
|
||||
log.info("存在");
|
||||
return PemUtil.loadPrivateKey(inputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取证书管理器实例
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Verifier getVerifier() throws GeneralSecurityException, IOException, HttpCodeException, NotFoundException {
|
||||
|
||||
log.info("获取证书管理器实例");
|
||||
|
||||
//获取商户私钥
|
||||
PrivateKey privateKey = getPrivateKey(keyPemPath);
|
||||
|
||||
//私钥签名对象
|
||||
PrivateKeySigner privateKeySigner = new PrivateKeySigner(serialNo, privateKey);
|
||||
|
||||
//身份认证对象
|
||||
WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
|
||||
|
||||
// 使用定时更新的签名验证器,不需要传入证书
|
||||
CertificatesManager certificatesManager = CertificatesManager.getInstance();
|
||||
certificatesManager.putMerchant(mchId,wechatPay2Credentials,apiV3Key.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return certificatesManager.getVerifier(mchId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取支付http请求对象
|
||||
* @param verifier
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "wxPayClient")
|
||||
public CloseableHttpClient getWxPayClient(Verifier verifier) {
|
||||
|
||||
//获取商户私钥
|
||||
PrivateKey privateKey = getPrivateKey(keyPemPath);
|
||||
|
||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||
.withMerchant(mchId, serialNo, privateKey)
|
||||
.withValidator(new WechatPay2Validator(verifier));
|
||||
|
||||
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取HttpClient,无需进行应答签名验证,跳过验签的流程
|
||||
*/
|
||||
@Bean(name = "wxPayNoSignClient")
|
||||
public CloseableHttpClient getWxPayNoSignClient(){
|
||||
|
||||
//获取商户私钥
|
||||
PrivateKey privateKey = getPrivateKey(keyPemPath);
|
||||
|
||||
//用于构造HttpClient
|
||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||
//设置商户信息
|
||||
.withMerchant(mchId, serialNo, privateKey)
|
||||
//无需进行签名验证、通过withValidator((response) -> true)实现
|
||||
.withValidator((response) -> true);
|
||||
|
||||
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
package com.ruoyi.payConfig;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @Author:
|
||||
* @Description:
|
||||
**/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class WechatPayRequest {
|
||||
@Resource
|
||||
private CloseableHttpClient wxPayClient;
|
||||
public String wechatHttpGet(String url) {
|
||||
try {
|
||||
// 拼接请求参数
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
httpGet.setHeader("Accept", "application/json");
|
||||
|
||||
//完成签名并执行请求
|
||||
CloseableHttpResponse response = wxPayClient.execute(httpGet);
|
||||
|
||||
return getResponseBody(response);
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String wechatHttpPost(String url,String paramsStr) {
|
||||
try {
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
StringEntity entity = new StringEntity(paramsStr, "utf-8");
|
||||
entity.setContentType("application/json");
|
||||
httpPost.setEntity(entity);
|
||||
httpPost.setHeader("Accept", "application/json");
|
||||
|
||||
CloseableHttpResponse response = wxPayClient.execute(httpPost);
|
||||
return getResponseBody(response);
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String getResponseBody(CloseableHttpResponse response) throws IOException {
|
||||
|
||||
//响应体
|
||||
HttpEntity entity = response.getEntity();
|
||||
String body = entity==null?"":EntityUtils.toString(entity);
|
||||
//响应状态码
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
//处理成功,204是,关闭订单时微信返回的正常状态码
|
||||
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
|
||||
log.info("成功, 返回结果 = " + body);
|
||||
} else {
|
||||
String msg = "微信支付请求失败,响应码 = " + statusCode + ",返回结果 = " + body;
|
||||
log.error(msg);
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@ -1,78 +0,0 @@
|
||||
package com.ruoyi.payConfig;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum WechatPayUrlEnum {
|
||||
|
||||
|
||||
/**
|
||||
* native
|
||||
*/
|
||||
NATIVE("native"),
|
||||
/**
|
||||
* app
|
||||
*/
|
||||
APP("app"),
|
||||
/**
|
||||
* h5
|
||||
*/
|
||||
H5("h5"),
|
||||
/**
|
||||
* jsapi
|
||||
*/
|
||||
JSAPI("jsapi"),
|
||||
|
||||
/**
|
||||
* 小程序jsapi
|
||||
*/
|
||||
SUB_JSAPI("sub_jsapi"),
|
||||
|
||||
/**
|
||||
* Native下单
|
||||
*/
|
||||
PAY_TRANSACTIONS("/pay/transactions/"),
|
||||
|
||||
/**
|
||||
* Native下单
|
||||
*/
|
||||
NATIVE_PAY_V2("/pay/unifiedorder"),
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*/
|
||||
ORDER_QUERY_BY_NO("/pay/transactions/out-trade-no/"),
|
||||
|
||||
/**
|
||||
* 关闭订单
|
||||
*/
|
||||
CLOSE_ORDER_BY_NO("/pay/transactions/out-trade-no/%s/close"),
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
DOMESTIC_REFUNDS("/refund/domestic/refunds"),
|
||||
|
||||
/**
|
||||
* 查询单笔退款
|
||||
*/
|
||||
DOMESTIC_REFUNDS_QUERY("/refund/domestic/refunds/"),
|
||||
|
||||
/**
|
||||
* 申请交易账单
|
||||
*/
|
||||
TRADE_BILLS("/bill/tradebill"),
|
||||
|
||||
/**
|
||||
* 申请资金账单
|
||||
*/
|
||||
FUND_FLOW_BILLS("/bill/fundflowbill");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
}
|
||||
@ -1,150 +0,0 @@
|
||||
package com.ruoyi.payConfig;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||
|
||||
/**
|
||||
* @Author:
|
||||
* @Description:
|
||||
**/
|
||||
@Slf4j
|
||||
public class WechatPayValidator {
|
||||
/**
|
||||
* 应答超时时间,单位为分钟
|
||||
*/
|
||||
private static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||
private final Verifier verifier;
|
||||
private final String requestId;
|
||||
private final String body;
|
||||
|
||||
|
||||
public WechatPayValidator(Verifier verifier, String requestId, String body) {
|
||||
this.verifier = verifier;
|
||||
this.requestId = requestId;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("parameter error: " + message);
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("signature verify fail: " + message);
|
||||
}
|
||||
|
||||
public final boolean validate(HttpServletRequest request) {
|
||||
try {
|
||||
//处理请求参数
|
||||
validateParameters(request);
|
||||
|
||||
//构造验签名串
|
||||
String message = buildMessage(request);
|
||||
|
||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||
|
||||
//验签
|
||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||
serial, message, signature, requestId);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validateParameters(HttpServletRequest request) {
|
||||
|
||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||
|
||||
String header = null;
|
||||
for (String headerName : headers) {
|
||||
header = request.getHeader(headerName);
|
||||
if (header == null) {
|
||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
//判断请求是否过期
|
||||
String timestampStr = header;
|
||||
try {
|
||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||
// 拒绝过期请求
|
||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
} catch (DateTimeException | NumberFormatException e) {
|
||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildMessage(HttpServletRequest request) {
|
||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||
return timestamp + "\n"
|
||||
+ nonce + "\n"
|
||||
+ body + "\n";
|
||||
}
|
||||
|
||||
private String getResponseBody(CloseableHttpResponse response) throws IOException {
|
||||
HttpEntity entity = response.getEntity();
|
||||
return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 对称解密,异步通知的加密数据
|
||||
* @param resource 加密数据
|
||||
* @param apiV3Key apiV3密钥
|
||||
* @param type 1-支付,2-退款
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> decryptFromResource(String resource,String apiV3Key,Integer type) {
|
||||
|
||||
String msg = type==1?"支付成功":"退款成功";
|
||||
log.info(msg+",回调通知,密文解密");
|
||||
try {
|
||||
//通知数据
|
||||
Map<String, String> resourceMap = JSONObject.parseObject(resource, new TypeReference<Map<String, String>>() {
|
||||
});
|
||||
//数据密文
|
||||
String ciphertext = resourceMap.get("ciphertext");
|
||||
//随机串
|
||||
String nonce = resourceMap.get("nonce");
|
||||
//附加数据
|
||||
String associatedData = resourceMap.get("associated_data");
|
||||
|
||||
log.info("密文: {}", ciphertext);
|
||||
AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
|
||||
String resourceStr = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
|
||||
nonce.getBytes(StandardCharsets.UTF_8),
|
||||
ciphertext);
|
||||
|
||||
log.info(msg+",回调通知,解密结果 : {}", resourceStr);
|
||||
return JSONObject.parseObject(resourceStr, new TypeReference<Map<String, Object>>(){});
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException("回调参数,解密失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
9
ruoyi-admin/src/main/resources/pub_key.pem
Normal file
9
ruoyi-admin/src/main/resources/pub_key.pem
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnyLw8B8x3B+jWpCxiSeU
|
||||
L+7NjFjx34Q44zlyRq6RXnz9xMFJXZq7HLv4YA9GcKyniF6aq7TvelKV8NUE8Ogd
|
||||
fdOEZr2Gc/W15nz1RAo5Fu2K9q9IsZlQ4pM+HT9oqu4qVCrsPZEPbr11szQZjqtf
|
||||
WdpZhRmiFzQRui0V0xzOQcd0GhicVhN5uMOekFqTALCq9JcWUl6Ti0fF4I4wH4kZ
|
||||
iZVEkPTcXQACEUWRCH7hbRvluF1dEr87I/hdp98C1lo1UzQWHimVmFD8t0wHgnyO
|
||||
qgSog353Hu59zkPB6qdraNNAvvOScOD8S/U57Nc4NXPXHOua1ZekwbE7lw/AvOcJ
|
||||
zQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Loading…
Reference in New Issue
Block a user