Commit bae82627 authored by 刘李鹏's avatar 刘李鹏

支付宝示例完成

parent 82f0a880
......@@ -129,7 +129,11 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15</artifactId>
<version>1.45</version>
</dependency>
<!--cache-->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
......
......@@ -42,6 +42,12 @@ public class AcquirerProperties implements Serializable{
private String payCertKey;
private String payRootCertNo;
private String payRootCertKey;
private String productCode;
//feature
private AccessCode accessCode;
......@@ -119,6 +125,30 @@ public class AcquirerProperties implements Serializable{
this.name = name;
}
public String getPayRootCertNo() {
return payRootCertNo;
}
public void setPayRootCertNo(String payRootCertNo) {
this.payRootCertNo = payRootCertNo;
}
public String getPayRootCertKey() {
return payRootCertKey;
}
public void setPayRootCertKey(String payRootCertKey) {
this.payRootCertKey = payRootCertKey;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getSecretKey() {
return secretKey;
}
......@@ -315,6 +345,7 @@ public class AcquirerProperties implements Serializable{
sb.append(", secretType='").append(secretType).append('\'');
sb.append(", signType='").append(signType).append('\'');
sb.append(", payCertNo='").append(payCertNo).append('\'');
sb.append(", payRootCertNo='").append(payRootCertNo).append('\'');
sb.append(", accessCode=").append(accessCode);
sb.append(", accessType=").append(accessType);
sb.append(", accessMethod='").append(accessMethod).append('\'');
......
......@@ -14,12 +14,14 @@ import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
/**
......@@ -49,6 +51,8 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
*/
X509Certificate payCerKey;
ObjectMapper objectMapper = new ObjectMapper();
/**
* 支付初始化
* 1. 初始化私钥
......@@ -82,7 +86,6 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
@Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
String outTradeNo = UUID.randomUUID().toString().replace("-", "");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode bodyNode = objectMapper.createObjectNode();
// 转换金额为分
BigInteger amount = new BigDecimal(payRequestData.getAmount()).multiply(new BigDecimal(100)).toBigInteger();
......@@ -108,17 +111,22 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
default:
}
bodyNode.set("scene_info", sceneInfo);
String requestBody = bodyNode.toString();
return doExecute(requestBody);
return doExecute(bodyNode);
}
/**
* 发起请求
*
* @param requestBody
* @param requestNode
* @return
*/
private JsonNode doExecute(String requestBody) {
private JsonNode doExecute(ObjectNode requestNode) {
String requestBody = "";
try {
requestBody = objectMapper.writeValueAsString(requestNode);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
long timestamp = System.currentTimeMillis() / 1000;
String nonceStr = UUID.randomUUID().toString().replace("-", "");
String signText = joining("\n", "POST", properties.getPayAccess(), String.valueOf(timestamp), nonceStr, requestBody);
......@@ -128,9 +136,9 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
.uri(properties.getPayAccess())
.header("Authorization", SCHEMA.concat(token))
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody).exchange();
.bodyValue(requestBody)
.exchange();
ClientResponse response = mono.block();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode bodyJsonNode = objectMapper.createObjectNode();
if (response != null) {
Mono<String> resultMono = response.bodyToMono(String.class);
......@@ -156,11 +164,11 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
if (verify(wsSignText, signature)) {
return bodyJsonNode;
}
// TODO: 签名校验失败,做异常处理
// throw new Exception("签名校验失败");
// TODO: 签名校验失败,做异常处理
throw new RuntimeException("签名校验失败");
} else {
// TODO: 微信返回异常,做异常处理
// throw new Exception("微信返回异常,做异常处理");
// TODO: 返回异常,做异常处理
throw new RuntimeException("返回异常,做异常处理");
}
}
return bodyJsonNode;
......@@ -254,7 +262,28 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
}
}
/**
* 获取公钥。
*
* @param certString 公钥文件内容(required)
* @return 私钥对象
*/
public static PublicKey getPublicKey(String certString) throws IOException {
try {
String publicKey = certString
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(
new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持RSA", e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException("无效的密钥格式");
}
}
/**
* 字符串数组拼接为字符串
......
......@@ -4,6 +4,7 @@ import cn.quant.baa.pay.acquirer.AcquirerConfiguration;
import cn.quant.baa.pay.acquirer.AcquirerConfigurer;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.acquirer.weixin.AlipayMerchantAcquirer;
import cn.quant.baa.pay.acquirer.weixin.WeiXinMerchantAcquirer;
import cn.quant.baa.pay.jpa.entity.*;
import cn.quant.baa.pay.jpa.repository.*;
......@@ -90,6 +91,10 @@ public class ServerConfiguration {
WeiXinMerchantAcquirer acquirer = new WeiXinMerchantAcquirer();
acquirer.init(property);
merchantAcquirer.register(acquirer);
} else if ("ALIP".equals(property.getPayChanCode())) {
AlipayMerchantAcquirer acquirer = new AlipayMerchantAcquirer();
acquirer.init(property);
merchantAcquirer.register(acquirer);
}
}
return merchantAcquirer;
......
......@@ -5,6 +5,7 @@ package cn.quant.baa.pay.dict;
*/
public enum AccessCode {
WEB("电脑网站支付"),
APP("应用支付"),
H5("H5页支付"),
JS("网页、小程序支付");
......
......@@ -44,13 +44,18 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable {
@Column(name = "PAY_PUBLIC_KEY", nullable = false, length = 255)
private String payPublicKey;
@Column(name = "PAY_CERT_NO", nullable = true, length = 64)
private String payCertNo;
@Column(name = "PAY_CERT_KEY", nullable = true, length = 2000)
private String payCertKey;
@Column(name = "PAY_ROOT_CERT_NO", nullable = true, length = 64)
private String payRootCertNo;
@Column(name = "PAY_ROOT_CERT_KEY", nullable = true, length = 4000)
private String payRootCertKey;
public PayAccountIds getIds() {
return ids;
}
......@@ -139,6 +144,22 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable {
this.payCertKey = payCertKey;
}
public String getPayRootCertNo() {
return payRootCertNo;
}
public void setPayRootCertNo(String payRootCertNo) {
this.payRootCertNo = payRootCertNo;
}
public String getPayRootCertKey() {
return payRootCertKey;
}
public void setPayRootCertKey(String payRootCertKey) {
this.payRootCertKey = payRootCertKey;
}
@Override
public String persistenceKey() {
return ids.persistenceKey();
......
......@@ -32,6 +32,9 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable
@Column(name = "PAY_ACCESS", nullable = false, length = 255)
private String payAccess;
@Column(name = "PRODUCT_CODE", nullable = false, length = 255)
private String productCode;
@Column(name = "REFUND_ACCESS", nullable = false, length = 255)
private String refundAccess;
......@@ -78,6 +81,14 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable
this.payAccess = payAccess;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getRefundAccess() {
return refundAccess;
}
......
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