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

支付宝示例完成

parent 82f0a880
...@@ -129,7 +129,11 @@ ...@@ -129,7 +129,11 @@
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId> <artifactId>jackson-datatype-hibernate5</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15</artifactId>
<version>1.45</version>
</dependency>
<!--cache--> <!--cache-->
<dependency> <dependency>
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.ben-manes.caffeine</groupId>
......
...@@ -42,6 +42,12 @@ public class AcquirerProperties implements Serializable{ ...@@ -42,6 +42,12 @@ public class AcquirerProperties implements Serializable{
private String payCertKey; private String payCertKey;
private String payRootCertNo;
private String payRootCertKey;
private String productCode;
//feature //feature
private AccessCode accessCode; private AccessCode accessCode;
...@@ -119,6 +125,30 @@ public class AcquirerProperties implements Serializable{ ...@@ -119,6 +125,30 @@ public class AcquirerProperties implements Serializable{
this.name = name; 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() { public String getSecretKey() {
return secretKey; return secretKey;
} }
...@@ -315,6 +345,7 @@ public class AcquirerProperties implements Serializable{ ...@@ -315,6 +345,7 @@ public class AcquirerProperties implements Serializable{
sb.append(", secretType='").append(secretType).append('\''); sb.append(", secretType='").append(secretType).append('\'');
sb.append(", signType='").append(signType).append('\''); sb.append(", signType='").append(signType).append('\'');
sb.append(", payCertNo='").append(payCertNo).append('\''); sb.append(", payCertNo='").append(payCertNo).append('\'');
sb.append(", payRootCertNo='").append(payRootCertNo).append('\'');
sb.append(", accessCode=").append(accessCode); sb.append(", accessCode=").append(accessCode);
sb.append(", accessType=").append(accessType); sb.append(", accessType=").append(accessType);
sb.append(", accessMethod='").append(accessMethod).append('\''); sb.append(", accessMethod='").append(accessMethod).append('\'');
......
package cn.quant.baa.pay.acquirer.weixin;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.model.web.PayRequestData;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriUtils;
import reactor.core.publisher.Mono;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Administrator on 2021/8/31 0031.
*/
public class AlipayMerchantAcquirer extends MerchantAcquirer {
private WebClient webClient;
private String signType = "RSA2";
private String charset = "utf-8";
private static BouncyCastleProvider provider;
static {
provider = new BouncyCastleProvider();
Security.addProvider(provider);
}
/**
* 商户私钥
*/
PrivateKey privateKey;
/**
* 支付宝公钥
*/
X509Certificate payPublicKey;
/**
* 应用公钥
*/
X509Certificate payCertKey;
/**
* 支付宝根证书
*/
X509Certificate[] payRootCertKey;
ObjectMapper objectMapper = new ObjectMapper();
/**
* 支付初始化
* 1. 初始化私钥
* 2. 初始化平台证书
* 3. 初始化webClient
*
* @param properties
* @return
* @throws Exception
*/
@Override
public MerchantAcquirer init(AcquirerProperties properties) throws Exception {
// super.init(properties);
this.properties = properties;
privateKey = getPrivateKey(properties.getPrivateKey());
payPublicKey = loadCertificate(properties.getPayPublicKey());
payCertKey = loadCertificate(properties.getPayCertKey());
payRootCertKey = loadCertificates(properties.getPayRootCertKey());
this.webClient = WebClient.builder()
.baseUrl(properties.getDomain())
.defaultHeader("Accept", "application/json")
.defaultHeader("User-Agent", "QuantGroup PayCenter Java Api")
.defaultHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + charset)
.build();
return this;
}
@Override
public Object code() {
return this.properties.getMchChanId().toString();
}
@Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("out_trade_no", payRequestData.getOutTradeNo());
bodyNode.put("total_amount", payRequestData.getAmount());
bodyNode.put("subject", payRequestData.getSubject());
bodyNode.put("body", payRequestData.getSubject());
bodyNode.put("product_code", properties.getProductCode());
return doWebExecute(bodyNode);
// String outTradeNo = "11111111218";
// bodyNode.put("out_trade_no", outTradeNo);
// return doExecute(bodyNode);
}
/**
* App支付发起请求
*
* @param bodyNode
* @return
*/
private JsonNode doAppExecute(ObjectNode bodyNode) {
ObjectNode params = buildParams(bodyNode);
TreeMap<String, String> sortedParams = getSortedMap(params);
ObjectNode body = objectMapper.createObjectNode();
body.put("data", buildQuery(sortedParams));
return body;
}
/**
* web支付发起请求
* alipay.trade.wap.pay
* alipay.trade.page.pay
*
* @param bodyNode
* @return
*/
private JsonNode doWebExecute(ObjectNode bodyNode) {
ObjectNode params = buildParams(bodyNode);
TreeMap<String, String> sortedParams = getSortedMap(params);
String url = String.format("%s%s?%s", properties.getDomain(), properties.getPayAccess(), buildQuery(sortedParams));
ObjectNode body = objectMapper.createObjectNode();
body.put("data", url);
return body;
}
/**
* 发起请求
*
* @param bodyNode
* @return
*/
private JsonNode doExecute(ObjectNode bodyNode) {
ObjectNode params = buildParams(bodyNode);
params.remove("biz_content");
Map<String, String> sortedParams = objectMapper.convertValue(params, new TypeReference<Map<String, String>>(){});
URI uri = URI.create(String.format("%s%s?%s", properties.getDomain(), properties.getPayAccess(), buildQuery(sortedParams)));
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
try {
formData.add("biz_content", objectMapper.writeValueAsString(bodyNode));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
Mono<ClientResponse> mono = webClient.post()
.uri(uri)
.body(BodyInserters.fromFormData(formData))
.exchange();
ClientResponse response = mono.block();
JsonNode bodyJsonNode = objectMapper.createObjectNode();
if (response != null) {
Mono<String> resultMono = response.bodyToMono(String.class);
String bodyRes = resultMono.block();
Pattern pattern = Pattern.compile("[a-zA-Z_0-9]*_response"); //去掉空格符合换行符
Matcher matcher = pattern.matcher(bodyRes);
String body = matcher.replaceAll("response");
try {
bodyJsonNode = objectMapper.readTree(body);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
if (response.statusCode().value() >= 200 && response.statusCode().value() < 300) {
//支付宝公钥号
String certSN = bodyJsonNode.get("alipay_cert_sn").asText();
if (!getPublicKeyCertSN().equals(certSN)) {
// TODO: 证书可能过期了,需要处理支付宝公钥过期的情况
throw new RuntimeException("支付宝公钥过期");
}
//支付宝签名
String signature = bodyJsonNode.get("sign").asText();
//签名信息
String signText = bodyJsonNode.get("response").toString();
if (verify(signText, signature)) {
return bodyJsonNode;
}
// TODO: 签名校验失败,做异常处理
throw new RuntimeException("签名校验失败");
} else {
// TODO: 返回异常,做异常处理
throw new RuntimeException("返回异常,做异常处理");
}
}
return bodyJsonNode;
}
public ObjectNode buildParams(ObjectNode bizContent) {
ObjectNode paramNode = objectMapper.createObjectNode();
paramNode.put("method", properties.getAccessMethod());
// paramNode.put("method", "alipay.trade.query");
paramNode.put("version", properties.getVersion());
paramNode.put("app_id", properties.getPayAcctId());
paramNode.put("sign_type", signType);
paramNode.put("notify_url", bizContent.get("notify_url"));
paramNode.put("return_url", bizContent.get("return_url"));
paramNode.put("charset", charset);
paramNode.put("app_cert_sn", properties.getPayCertNo());
paramNode.put("alipay_root_cert_sn", properties.getPayRootCertNo());
bizContent.remove("notify_url");
bizContent.remove("return_url");
Long timestamp = System.currentTimeMillis();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
paramNode.put("timestamp", df.format(new Date(timestamp)));
paramNode.put("format", "json");
// paramNode.put("auth_token", "");
try {
paramNode.put("biz_content", objectMapper.writeValueAsString(bizContent));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
TreeMap<String, String> sortedParams = getSortedMap(paramNode);
String signContent = getSignContent(sortedParams);
paramNode.put("sign", sign(signContent));
return paramNode;
}
public String buildQuery(Map<String, String> params) {
if (params == null || params.isEmpty()) {
return null;
}
StringBuilder query = new StringBuilder();
Set<Map.Entry<String, String>> entries = params.entrySet();
boolean hasParam = false;
for (Map.Entry<String, String> entry : entries) {
String name = entry.getKey();
String value = entry.getValue();
// 忽略参数名或参数值为空的参数
if (areNotEmpty(name, value)) {
if (hasParam) {
query.append("&");
} else {
hasParam = true;
}
query.append(name).append("=").append(UriUtils.encode(value, charset));
}
}
return query.toString();
}
public TreeMap<String, String> getSortedMap(ObjectNode paramNode) {
return objectMapper.convertValue(paramNode, new TypeReference<TreeMap<String, String>>(){});
}
/**
* @param sortedParams
* @return
*/
public String getSignContent(TreeMap<String, String> sortedParams) {
StringBuilder content = new StringBuilder();
List<String> keys = new ArrayList<String>(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
for (String key : keys) {
String value = sortedParams.get(key);
if (areNotEmpty(key, value)) {
content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
index++;
}
}
return content.toString();
}
/**
* 检查指定的字符串是否为空。
* <ul>
* <li>SysUtils.isEmpty(null) = true</li>
* <li>SysUtils.isEmpty("") = true</li>
* <li>SysUtils.isEmpty(" ") = true</li>
* <li>SysUtils.isEmpty("abc") = false</li>
* </ul>
*
* @param value 待检查的字符串
* @return true/false
*/
public static boolean isEmpty(String value) {
int strLen;
if (value == null || (strLen = value.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(value.charAt(i)) == false)) {
return false;
}
}
return true;
}
/**
* 检查指定的字符串列表是否不为空。
*/
public static boolean areNotEmpty(String... values) {
boolean result = true;
if (values == null || values.length == 0) {
result = false;
} else {
for (String value : values) {
result &= !isEmpty(value);
}
}
return result;
}
/**
* 签名
*
* @param signText 需要签名的字符串
* @return
*/
public String sign(String signText) {
try {
Signature sign = Signature.getInstance(properties.getSignType());
sign.initSign(this.privateKey);
sign.update(signText.getBytes());
return Base64.getEncoder().encodeToString(sign.sign());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
} catch (SignatureException e) {
throw new RuntimeException("签名计算失败", e);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的私钥", e);
}
}
/**
* 获取证书。
*
* @param certString 证书内容
* @return X509证书
*/
public X509Certificate[] loadCertificates(String certString) {
try {
ByteArrayInputStream fis = new ByteArrayInputStream(certString.getBytes());
CertificateFactory cf = CertificateFactory.getInstance("X509", provider);
Collection<? extends Certificate> certs = cf.generateCertificates(fis);
return (X509Certificate[]) certs.toArray(new X509Certificate[certs.size()]);
} catch (CertificateExpiredException var3) {
throw new RuntimeException("证书已过期", var3);
} catch (CertificateNotYetValidException var4) {
throw new RuntimeException("证书尚未生效", var4);
} catch (CertificateException var5) {
throw new RuntimeException("无效的证书", var5);
}
}
/**
* 获取证书。
*
* @param certString 证书内容
* @return X509证书
*/
public X509Certificate loadCertificate(String certString) {
try {
ByteArrayInputStream fis = new ByteArrayInputStream(certString.getBytes());
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
cert.checkValidity();
return cert;
} catch (CertificateExpiredException var3) {
throw new RuntimeException("证书已过期", var3);
} catch (CertificateNotYetValidException var4) {
throw new RuntimeException("证书尚未生效", var4);
} catch (CertificateException var5) {
throw new RuntimeException("无效的证书", var5);
}
}
/**
* RSA验签名检查
*
* @param content 待签名数据
* @param signature 签名值
* @return 布尔值
*/
public boolean verify(String content, String signature) {
try {
Signature sign = Signature.getInstance(properties.getSignType());
sign.initVerify(payPublicKey);
sign.update(content.getBytes());
return sign.verify(Base64.getDecoder().decode(signature));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
} catch (SignatureException e) {
throw new RuntimeException("签名验证过程发生了错误", e);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的证书", e);
}
}
/**
* 获取私钥。
*
* @param certString 私钥文件内容(required)
* @return 私钥对象
*/
public PrivateKey getPrivateKey(String certString) {
try {
String privateKey = certString
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(
new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持RSA", e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException("无效的密钥格式");
}
}
/**
* 获取公钥。
*
* @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("无效的密钥格式");
}
}
/**
* 获取支付宝私钥证书号
* @return
*/
public String getPublicKeyCertSN() {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update((payPublicKey.getIssuerX500Principal().getName() + payPublicKey.getSerialNumber()).getBytes());
String certSN = new BigInteger(1, md.digest()).toString(16);
//BigInteger会把0省略掉,需补全至32位
certSN = fillMD5(certSN);
return certSN;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
private String fillMD5(String md5) {
return md5.length() == 32 ? md5 : fillMD5("0" + md5);
}
}
\ No newline at end of file
...@@ -14,12 +14,14 @@ import org.springframework.web.reactive.function.client.WebClient; ...@@ -14,12 +14,14 @@ import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*; import java.util.*;
/** /**
...@@ -49,6 +51,8 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -49,6 +51,8 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
*/ */
X509Certificate payCerKey; X509Certificate payCerKey;
ObjectMapper objectMapper = new ObjectMapper();
/** /**
* 支付初始化 * 支付初始化
* 1. 初始化私钥 * 1. 初始化私钥
...@@ -82,7 +86,6 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -82,7 +86,6 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
@Override @Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) { public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
String outTradeNo = UUID.randomUUID().toString().replace("-", ""); String outTradeNo = UUID.randomUUID().toString().replace("-", "");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode bodyNode = objectMapper.createObjectNode(); ObjectNode bodyNode = objectMapper.createObjectNode();
// 转换金额为分 // 转换金额为分
BigInteger amount = new BigDecimal(payRequestData.getAmount()).multiply(new BigDecimal(100)).toBigInteger(); BigInteger amount = new BigDecimal(payRequestData.getAmount()).multiply(new BigDecimal(100)).toBigInteger();
...@@ -108,17 +111,22 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -108,17 +111,22 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
default: default:
} }
bodyNode.set("scene_info", sceneInfo); bodyNode.set("scene_info", sceneInfo);
String requestBody = bodyNode.toString(); return doExecute(bodyNode);
return doExecute(requestBody);
} }
/** /**
* 发起请求 * 发起请求
* *
* @param requestBody * @param requestNode
* @return * @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; long timestamp = System.currentTimeMillis() / 1000;
String nonceStr = UUID.randomUUID().toString().replace("-", ""); String nonceStr = UUID.randomUUID().toString().replace("-", "");
String signText = joining("\n", "POST", properties.getPayAccess(), String.valueOf(timestamp), nonceStr, requestBody); String signText = joining("\n", "POST", properties.getPayAccess(), String.valueOf(timestamp), nonceStr, requestBody);
...@@ -128,9 +136,9 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -128,9 +136,9 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
.uri(properties.getPayAccess()) .uri(properties.getPayAccess())
.header("Authorization", SCHEMA.concat(token)) .header("Authorization", SCHEMA.concat(token))
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody).exchange(); .bodyValue(requestBody)
.exchange();
ClientResponse response = mono.block(); ClientResponse response = mono.block();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode bodyJsonNode = objectMapper.createObjectNode(); JsonNode bodyJsonNode = objectMapper.createObjectNode();
if (response != null) { if (response != null) {
Mono<String> resultMono = response.bodyToMono(String.class); Mono<String> resultMono = response.bodyToMono(String.class);
...@@ -156,11 +164,11 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -156,11 +164,11 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
if (verify(wsSignText, signature)) { if (verify(wsSignText, signature)) {
return bodyJsonNode; return bodyJsonNode;
} }
// TODO: 签名校验失败,做异常处理 // TODO: 签名校验失败,做异常处理
// throw new Exception("签名校验失败"); throw new RuntimeException("签名校验失败");
} else { } else {
// TODO: 微信返回异常,做异常处理 // TODO: 返回异常,做异常处理
// throw new Exception("微信返回异常,做异常处理"); throw new RuntimeException("返回异常,做异常处理");
} }
} }
return bodyJsonNode; return bodyJsonNode;
...@@ -254,7 +262,28 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer { ...@@ -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; ...@@ -4,6 +4,7 @@ import cn.quant.baa.pay.acquirer.AcquirerConfiguration;
import cn.quant.baa.pay.acquirer.AcquirerConfigurer; import cn.quant.baa.pay.acquirer.AcquirerConfigurer;
import cn.quant.baa.pay.acquirer.AcquirerProperties; import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.MerchantAcquirer; 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.acquirer.weixin.WeiXinMerchantAcquirer;
import cn.quant.baa.pay.jpa.entity.*; import cn.quant.baa.pay.jpa.entity.*;
import cn.quant.baa.pay.jpa.repository.*; import cn.quant.baa.pay.jpa.repository.*;
...@@ -90,6 +91,10 @@ public class ServerConfiguration { ...@@ -90,6 +91,10 @@ public class ServerConfiguration {
WeiXinMerchantAcquirer acquirer = new WeiXinMerchantAcquirer(); WeiXinMerchantAcquirer acquirer = new WeiXinMerchantAcquirer();
acquirer.init(property); acquirer.init(property);
merchantAcquirer.register(acquirer); merchantAcquirer.register(acquirer);
} else if ("ALIP".equals(property.getPayChanCode())) {
AlipayMerchantAcquirer acquirer = new AlipayMerchantAcquirer();
acquirer.init(property);
merchantAcquirer.register(acquirer);
} }
} }
return merchantAcquirer; return merchantAcquirer;
......
...@@ -5,6 +5,7 @@ package cn.quant.baa.pay.dict; ...@@ -5,6 +5,7 @@ package cn.quant.baa.pay.dict;
*/ */
public enum AccessCode { public enum AccessCode {
WEB("电脑网站支付"),
APP("应用支付"), APP("应用支付"),
H5("H5页支付"), H5("H5页支付"),
JS("网页、小程序支付"); JS("网页、小程序支付");
......
...@@ -44,13 +44,18 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable { ...@@ -44,13 +44,18 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable {
@Column(name = "PAY_PUBLIC_KEY", nullable = false, length = 255) @Column(name = "PAY_PUBLIC_KEY", nullable = false, length = 255)
private String payPublicKey; private String payPublicKey;
@Column(name = "PAY_CERT_NO", nullable = true, length = 64) @Column(name = "PAY_CERT_NO", nullable = true, length = 64)
private String payCertNo; private String payCertNo;
@Column(name = "PAY_CERT_KEY", nullable = true, length = 2000) @Column(name = "PAY_CERT_KEY", nullable = true, length = 2000)
private String payCertKey; 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() { public PayAccountIds getIds() {
return ids; return ids;
} }
...@@ -139,6 +144,22 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable { ...@@ -139,6 +144,22 @@ public class PayAccountEntity extends OptimisticEntity implements Serializable {
this.payCertKey = payCertKey; 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 @Override
public String persistenceKey() { public String persistenceKey() {
return ids.persistenceKey(); return ids.persistenceKey();
......
...@@ -32,6 +32,9 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable ...@@ -32,6 +32,9 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable
@Column(name = "PAY_ACCESS", nullable = false, length = 255) @Column(name = "PAY_ACCESS", nullable = false, length = 255)
private String payAccess; private String payAccess;
@Column(name = "PRODUCT_CODE", nullable = false, length = 255)
private String productCode;
@Column(name = "REFUND_ACCESS", nullable = false, length = 255) @Column(name = "REFUND_ACCESS", nullable = false, length = 255)
private String refundAccess; private String refundAccess;
...@@ -78,6 +81,14 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable ...@@ -78,6 +81,14 @@ public class PayFeatureEntity extends DescriptionEntity implements Serializable
this.payAccess = payAccess; this.payAccess = payAccess;
} }
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getRefundAccess() { public String getRefundAccess() {
return refundAccess; 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