提交修改
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.DirectAPIv3JsapiPrepayResponse;
|
||||
import com.heyu.api.jsapi.dto.JsapiReqPayerInfo;
|
||||
import com.heyu.api.jsapi.utils.PemUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.security.Signature;
|
||||
|
||||
/**
|
||||
* JSAPI下单
|
||||
@ -59,6 +64,15 @@ public class JsapiPrepay {
|
||||
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,
|
||||
|
||||
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.jsapi.JsapiPrepay;
|
||||
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.PPageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -31,6 +32,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@ -78,6 +81,19 @@ public class AppOrderController {
|
||||
@Value("${eb.config.rabbitQueue.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
|
||||
@ -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("删除订单")
|
||||
@RequestMapping("/delete")
|
||||
public R add(@RequestBody VvTradeOrderDeleteDTO vvOrderRequest) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user