提交修改
This commit is contained in:
parent
42f8b98350
commit
6ad4cccb2a
@ -6,16 +6,21 @@ import com.heyu.api.jsapi.dto.CommonAmountInfo;
|
|||||||
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayRequest;
|
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayRequest;
|
||||||
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayResponse;
|
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayResponse;
|
||||||
import com.heyu.api.jsapi.dto.JsapiReqPayerInfo;
|
import com.heyu.api.jsapi.dto.JsapiReqPayerInfo;
|
||||||
|
import com.heyu.api.jsapi.utils.PemUtil;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
|
import java.security.Signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSAPI下单
|
* JSAPI下单
|
||||||
@ -59,6 +64,15 @@ public class JsapiPrepay {
|
|||||||
this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
|
this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static String getSign(String signatureStr, String privateKey) {
|
||||||
|
String replace = privateKey.replace("\\n", "\n");
|
||||||
|
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromPath(replace);
|
||||||
|
Signature sign = Signature.getInstance("SHA256withRSA");
|
||||||
|
sign.initSign(merchantPrivateKey);
|
||||||
|
sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Base64Utils.encodeToString(sign.sign());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public DirectAPIv3JsapiPrepayResponse prePay(Long tradeOrderId,
|
public DirectAPIv3JsapiPrepayResponse prePay(Long tradeOrderId,
|
||||||
|
|||||||
20
api-third/src/main/java/com/heyu/api/jsapi/dto/WxPayVO.java
Normal file
20
api-third/src/main/java/com/heyu/api/jsapi/dto/WxPayVO.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.heyu.api.jsapi.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WxPayVO {
|
||||||
|
// 预支付交易会话标识小程序下单接口返回的prepay_id参数值
|
||||||
|
private String prepayId;
|
||||||
|
// 随机字符串
|
||||||
|
private String nonceStr;
|
||||||
|
// 时间戳
|
||||||
|
private Long timeStamp;
|
||||||
|
// 签名
|
||||||
|
private String paySign;
|
||||||
|
// 商户号
|
||||||
|
private String mchid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
60
api-third/src/main/java/com/heyu/api/jsapi/utils/IOUtil.java
Normal file
60
api-third/src/main/java/com/heyu/api/jsapi/utils/IOUtil.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
package com.heyu.api.jsapi.utils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/** I/O工具 */
|
||||||
|
public class IOUtil {
|
||||||
|
|
||||||
|
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
|
private IOUtil() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换输入流为字节数组
|
||||||
|
*
|
||||||
|
* @param inputStream 输入流
|
||||||
|
* @return 字节数组
|
||||||
|
* @throws IOException 读取字节失败、关闭流失败等
|
||||||
|
*/
|
||||||
|
public static byte[] toByteArray(InputStream inputStream) throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
int nRead;
|
||||||
|
byte[] data = new byte[DEFAULT_BUFFER_SIZE];
|
||||||
|
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||||
|
buffer.write(data, 0, nRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换输入流为字符串
|
||||||
|
*
|
||||||
|
* @param inputStream 输入流
|
||||||
|
* @return UTF-8编码的字符串
|
||||||
|
* @throws IOException 读取字节失败、关闭流失败等
|
||||||
|
*/
|
||||||
|
public static String toString(InputStream inputStream) throws IOException {
|
||||||
|
return new String(toByteArray(inputStream), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径中读取字符串
|
||||||
|
*
|
||||||
|
* @param path 文件路径
|
||||||
|
* @return UTF-8编码的字符串
|
||||||
|
* @throws IOException 读取字节失败、关闭流失败等
|
||||||
|
*/
|
||||||
|
public static String loadStringFromPath(String path) throws IOException {
|
||||||
|
try (InputStream inputStream = Files.newInputStream(Paths.get(path))) {
|
||||||
|
return toString(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
227
api-third/src/main/java/com/heyu/api/jsapi/utils/PemUtil.java
Normal file
227
api-third/src/main/java/com/heyu/api/jsapi/utils/PemUtil.java
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
package com.heyu.api.jsapi.utils;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
|
||||||
|
/** PEM工具 */
|
||||||
|
public class PemUtil {
|
||||||
|
|
||||||
|
|
||||||
|
public static final int HEX = 16;
|
||||||
|
|
||||||
|
private PemUtil() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从字符串中加载RSA私钥。
|
||||||
|
*
|
||||||
|
* @param keyString 私钥字符串
|
||||||
|
* @return RSA私钥
|
||||||
|
*/
|
||||||
|
public static PrivateKey loadPrivateKeyFromString(String keyString) {
|
||||||
|
try {
|
||||||
|
keyString =
|
||||||
|
keyString
|
||||||
|
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||||
|
.replace("-----END PRIVATE KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
return KeyFactory.getInstance("RSA")
|
||||||
|
.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new UnsupportedOperationException(e);
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从字符串中加载指定算法的私钥
|
||||||
|
*
|
||||||
|
* @param keyString 私钥字符串
|
||||||
|
* @param algorithm 私钥算法
|
||||||
|
* @param provider the provider
|
||||||
|
* @return 私钥
|
||||||
|
*/
|
||||||
|
public static PrivateKey loadPrivateKeyFromString(
|
||||||
|
String keyString, String algorithm, String provider) {
|
||||||
|
try {
|
||||||
|
keyString =
|
||||||
|
keyString
|
||||||
|
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||||
|
.replace("-----END PRIVATE KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
return KeyFactory.getInstance(algorithm, provider)
|
||||||
|
.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new UnsupportedOperationException(e);
|
||||||
|
} catch (InvalidKeySpecException | NoSuchProviderException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从字符串中加载RSA公钥。
|
||||||
|
*
|
||||||
|
* @param keyString 公钥字符串
|
||||||
|
* @return RSA公钥
|
||||||
|
*/
|
||||||
|
public static PublicKey loadPublicKeyFromString(String keyString) {
|
||||||
|
try {
|
||||||
|
keyString =
|
||||||
|
keyString
|
||||||
|
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||||
|
.replace("-----END PUBLIC KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
return KeyFactory.getInstance("RSA")
|
||||||
|
.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new UnsupportedOperationException(e);
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载RSA私钥
|
||||||
|
*
|
||||||
|
* @param keyPath 私钥路径
|
||||||
|
* @return RSA私钥
|
||||||
|
*/
|
||||||
|
public static PrivateKey loadPrivateKeyFromPath(String keyPath) {
|
||||||
|
return loadPrivateKeyFromString(readKeyStringFromPath(keyPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载指定算法的私钥
|
||||||
|
*
|
||||||
|
* @param keyPath 私钥路径
|
||||||
|
* @param algorithm 私钥算法
|
||||||
|
* @param provider the provider
|
||||||
|
* @return 私钥
|
||||||
|
*/
|
||||||
|
public static PrivateKey loadPrivateKeyFromPath(
|
||||||
|
String keyPath, String algorithm, String provider) {
|
||||||
|
return loadPrivateKeyFromString(readKeyStringFromPath(keyPath), algorithm, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载RSA公钥
|
||||||
|
*
|
||||||
|
* @param keyPath 公钥路径
|
||||||
|
* @return RSA公钥
|
||||||
|
*/
|
||||||
|
public static PublicKey loadPublicKeyFromPath(String keyPath) {
|
||||||
|
return loadPublicKeyFromString(readKeyStringFromPath(keyPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String readKeyStringFromPath(String keyPath) {
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(keyPath)) {
|
||||||
|
return IOUtil.toString(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从输入流加载X.509证书
|
||||||
|
*
|
||||||
|
* @param inputStream 私钥输入流
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromStream(InputStream inputStream) {
|
||||||
|
try {
|
||||||
|
return (X509Certificate)
|
||||||
|
CertificateFactory.getInstance("X.509").generateCertificate(inputStream);
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从输入流加载X.509证书
|
||||||
|
*
|
||||||
|
* @param inputStream 私钥输入流
|
||||||
|
* @param provider the provider
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromStream(InputStream inputStream, String provider) {
|
||||||
|
try {
|
||||||
|
return (X509Certificate)
|
||||||
|
CertificateFactory.getInstance("X.509", provider).generateCertificate(inputStream);
|
||||||
|
} catch (CertificateException | NoSuchProviderException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载X.509证书
|
||||||
|
*
|
||||||
|
* @param certificatePath 证书文件路径
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromPath(String certificatePath) {
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(certificatePath)) {
|
||||||
|
return loadX509FromStream(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载X.509证书
|
||||||
|
*
|
||||||
|
* @param certificatePath 证书文件路径
|
||||||
|
* @param provider the provider
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromPath(String certificatePath, String provider) {
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(certificatePath)) {
|
||||||
|
return loadX509FromStream(inputStream, provider);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从字符串加载X.509证书
|
||||||
|
*
|
||||||
|
* @param certificateString 证书字符串
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromString(String certificateString) {
|
||||||
|
try (ByteArrayInputStream inputStream =
|
||||||
|
new ByteArrayInputStream(certificateString.getBytes(StandardCharsets.UTF_8))) {
|
||||||
|
return loadX509FromStream(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从字符串加载X.509证书
|
||||||
|
*
|
||||||
|
* @param certificateString 证书字符串
|
||||||
|
* @param provider the provider
|
||||||
|
* @return X.509证书
|
||||||
|
*/
|
||||||
|
public static X509Certificate loadX509FromString(String certificateString, String provider) {
|
||||||
|
try (ByteArrayInputStream inputStream =
|
||||||
|
new ByteArrayInputStream(certificateString.getBytes(StandardCharsets.UTF_8))) {
|
||||||
|
return loadX509FromStream(inputStream, provider);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSerialNumber(X509Certificate certificate) {
|
||||||
|
return certificate.getSerialNumber().toString(HEX).toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ import com.heyu.api.data.enums.RoleEnums;
|
|||||||
import com.heyu.api.data.utils.*;
|
import com.heyu.api.data.utils.*;
|
||||||
import com.heyu.api.jsapi.JsapiPrepay;
|
import com.heyu.api.jsapi.JsapiPrepay;
|
||||||
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayResponse;
|
import com.heyu.api.jsapi.dto.DirectAPIv3JsapiPrepayResponse;
|
||||||
|
import com.heyu.api.jsapi.dto.WxPayVO;
|
||||||
import com.heyu.api.utils.ISelect;
|
import com.heyu.api.utils.ISelect;
|
||||||
import com.heyu.api.utils.PPageUtils;
|
import com.heyu.api.utils.PPageUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -31,6 +32,8 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -78,6 +81,19 @@ public class AppOrderController {
|
|||||||
@Value("${eb.config.rabbitQueue.delayExchangeName}")
|
@Value("${eb.config.rabbitQueue.delayExchangeName}")
|
||||||
private String delayExchangeName;
|
private String delayExchangeName;
|
||||||
|
|
||||||
|
@Value("${eb.config.weixin.pay.appid}")
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
@Value("${eb.config.weixin.pay.mchid}")
|
||||||
|
private String mchid;
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${eb.config.weixin.pay.privateKeyFilePath}")
|
||||||
|
private String privateKey;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* https://api.1024api.com/api-interface/app/order/list
|
* https://api.1024api.com/api-interface/app/order/list
|
||||||
@ -347,12 +363,34 @@ public class AppOrderController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
Map<String,Object> map = new HashMap<>();
|
|
||||||
map.put("prepay_id",prepay_id);
|
|
||||||
return R.ok().setData(map);
|
|
||||||
|
|
||||||
|
WxPayVO vo = new WxPayVO();
|
||||||
|
Long timeStamp = System.currentTimeMillis() / 1000;
|
||||||
|
String nonceStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
|
||||||
|
|
||||||
|
String signatureStr = Stream.of(appid, String.valueOf(timeStamp), nonceStr, "prepay_id=" + prepay_id)
|
||||||
|
.collect(Collectors.joining("\n", "", "\n"));
|
||||||
|
|
||||||
|
// "timeStamp": "1414561699",
|
||||||
|
// "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
|
||||||
|
// "package": "prepay_id=wx201410272009395522657a690389285100",
|
||||||
|
// "signType": "RSA",
|
||||||
|
// "paySign": "oR9d",
|
||||||
|
|
||||||
|
String sign = JsapiPrepay.getSign(signatureStr, privateKey);
|
||||||
|
vo.setNonceStr(nonceStr);
|
||||||
|
vo.setTimeStamp(timeStamp);
|
||||||
|
vo.setMchid(mchid);
|
||||||
|
vo.setPaySign(sign);
|
||||||
|
vo.setPrepayId("prepay_id=" + prepay_id);
|
||||||
|
|
||||||
|
return R.ok().setData(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Describe("删除订单")
|
@Describe("删除订单")
|
||||||
@RequestMapping("/delete")
|
@RequestMapping("/delete")
|
||||||
public R add(@RequestBody VvTradeOrderDeleteDTO vvOrderRequest) {
|
public R add(@RequestBody VvTradeOrderDeleteDTO vvOrderRequest) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user