Commit 9398f372 authored by Administrator's avatar Administrator

创建项目

parent 26f29bcd
......@@ -31,6 +31,7 @@
<mapping class="cn.quant.baa.pay.jpa.entity.PayHistoryEntity"/>
<mapping class="cn.quant.baa.pay.jpa.entity.PayGoodsDetailEntity"/>
<mapping class="cn.quant.baa.pay.jpa.entity.StatusCodeEntity"/>
<mapping class="cn.quant.baa.pay.jpa.entity.BatchCycleTriggerEntity"/>
<!-- Drop and re-create the database schema on startup -->
<!--
......
......@@ -2,7 +2,6 @@ package cn.quant.baa.pay.acquirer;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.model.web.*;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Created by Administrator on 2021/9/1 0001.
......@@ -10,9 +9,9 @@ import com.fasterxml.jackson.databind.JsonNode;
public interface Acquirer {
Object code();
JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity);
JsonNode refund(RefundRequestData refundRequestData);
JsonNode checkPay(CheckPayRequestData checkPayRequestData);
JsonNode checkRefund(CheckRefundRequestData checkRefundRequestData);
JsonNode close(CloseRequestData closeRequestData);
ChannelResponse pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) throws Exception;
ChannelResponse refund(RefundRequestData refundRequestData) throws Exception;
ChannelResponse checkPay(CheckPayRequestData checkPayRequestData) throws Exception;
ChannelResponse checkRefund(CheckRefundRequestData checkRefundRequestData) throws Exception;
ChannelResponse close(CloseRequestData closeRequestData) throws Exception;
}
package cn.quant.baa.pay.acquirer;
/**
* Created by Administrator on 2021/9/23 0023.
*/
public abstract class AcquirerConstant {
public final static String HTTP_STATUS_TYPE= "HTTP_STAT";
public final static String COMMON_ERROR_CODE = "ERROR";
public final static String COMMON_ERROR_MESSAGE = "ERROR";
public final static String EXECUTE_PAY = "Pay";
public final static String EXECUTE_CHECK_PAY= "CheckPay";
public final static String EXECUTE_CHECK_REFUND= "CheckRefund";
public final static String EXECUTE_CLOSE= "Close";
public final static String EXECUTE_REFUND= "Refund";
}
package cn.quant.baa.pay.acquirer;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Created by Administrator on 2021/9/22 0022.
*/
public class ChannelResponse {
private boolean success;
private String code;
private String message;
private String requestId;
//当前使用的微信平台证书序列号
private String serial;
//微信服务器的时间戳
private String timestamp;
//微信服务器提供的随机串
private String nonce;
//微信平台签名
private String signature;
private String payUrl;
private String prepayId;
private JsonNode node;
public boolean getSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getPayUrl() {
return payUrl;
}
public void setPayUrl(String payUrl) {
this.payUrl = payUrl;
}
public String getPrepayId() {
return prepayId;
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public JsonNode getNode() {
return node;
}
public void setNode(JsonNode node) {
this.node = node;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ChannelResponse{");
sb.append("success=").append(success);
sb.append(", code='").append(code).append('\'');
sb.append(", message='").append(message).append('\'');
sb.append(", requestId='").append(requestId).append('\'');
sb.append(", serial='").append(serial).append('\'');
sb.append(", timestamp='").append(timestamp).append('\'');
sb.append(", nonce='").append(nonce).append('\'');
sb.append(", signature='").append(signature).append('\'');
sb.append(", payUrl='").append(payUrl).append('\'');
sb.append(", prepayId='").append(prepayId).append('\'');
sb.append(", node=").append(node);
sb.append('}');
return sb.toString();
}
}
......@@ -6,7 +6,6 @@ import cn.quant.spring.NotSupportedException;
import cn.quant.spring.security.Base64Cipher;
import cn.quant.spring.security.CharacterCipher;
import cn.quant.spring.util.RandomSequencer;
import com.fasterxml.jackson.databind.JsonNode;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
......@@ -65,27 +64,27 @@ public class MerchantAcquirer implements Acquirer {
}
@Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
public ChannelResponse pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) throws Exception {
return acquirers.get(payRequestData.getChanId()).pay(payRequestData, payHistoryEntity);
}
@Override
public JsonNode refund(RefundRequestData refundRequestData) {
public ChannelResponse refund(RefundRequestData refundRequestData) throws Exception {
return acquirers.get(refundRequestData.getChanId()).refund(refundRequestData);
}
@Override
public JsonNode checkPay(CheckPayRequestData checkPayRequestData) {
public ChannelResponse checkPay(CheckPayRequestData checkPayRequestData) throws Exception {
return acquirers.get(checkPayRequestData.getChanId()).checkPay(checkPayRequestData);
}
@Override
public JsonNode checkRefund(CheckRefundRequestData checkRefundRequestData) {
public ChannelResponse checkRefund(CheckRefundRequestData checkRefundRequestData) throws Exception {
return acquirers.get(checkRefundRequestData.getChanId()).checkRefund(checkRefundRequestData);
}
@Override
public JsonNode close(CloseRequestData closeRequestData) {
public ChannelResponse close(CloseRequestData closeRequestData) throws Exception {
return acquirers.get(closeRequestData.getChanId()).close(closeRequestData);
}
}
package cn.quant.baa.pay.acquirer.alipay;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.ChannelResponse;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.model.web.*;
......@@ -113,26 +114,27 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
}
@Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
public ChannelResponse 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());
switch (properties.getAccessCode()) {
case APP:
return doAppExecute(bodyNode);
case H5:
case WEB:
return doWebExecute(bodyNode);
default:
}
return doExecute(bodyNode);
// switch (properties.getAccessCode()) {
// case APP:
// return doAppExecute(bodyNode);
// case H5:
// case WEB:
// return doWebExecute(bodyNode);
// default:
// }
// return doExecute(bodyNode);
return null;
}
@Override
public JsonNode checkPay(CheckPayRequestData checkPayRequestData) {
public ChannelResponse checkPay(CheckPayRequestData checkPayRequestData) {
// String outTradeNo = "11111111218";
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("out_trade_no", checkPayRequestData.getOutTradeNo());
......@@ -140,7 +142,7 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
}
@Override
public JsonNode checkRefund(CheckRefundRequestData checkRefundRequestData) {
public ChannelResponse checkRefund(CheckRefundRequestData checkRefundRequestData) {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("out_trade_no", checkRefundRequestData.getOutTradeNo());
bodyNode.put("out_request_no", checkRefundRequestData.getOutRefundNo());
......@@ -148,14 +150,14 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
}
@Override
public JsonNode close(CloseRequestData closeRequestData) {
public ChannelResponse close(CloseRequestData closeRequestData) {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("out_trade_no", closeRequestData.getOutTradeNo());
return doExecute(bodyNode);
}
@Override
public JsonNode refund(RefundRequestData refundRequestData) {
public ChannelResponse refund(RefundRequestData refundRequestData) {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("out_trade_no", refundRequestData.getOutTradeNo());
bodyNode.put("refund_amount", refundRequestData.getRefundAmount());
......@@ -201,7 +203,7 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
* @param bodyNode
* @return
*/
private JsonNode doExecute(ObjectNode bodyNode) {
private ChannelResponse doExecute(ObjectNode bodyNode) {
ObjectNode params = buildParams(bodyNode);
params.remove("biz_content");
Map<String, String> sortedParams = objectMapper.convertValue(params, new TypeReference<Map<String, String>>(){});
......@@ -244,7 +246,7 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
//这里的斜杠替换是因为json解析之后自动去掉了转义符/,签名的时候需要再给加上
String signText = bodyJsonNode.get("response").toString().replace("/", "\\/");
if (verify(signText, signature)) {
return bodyJsonNode;
// return bodyJsonNode;
}
// TODO: 签名校验失败,做异常处理
throw new RuntimeException("签名校验失败");
......@@ -253,7 +255,8 @@ public class AlipayMerchantAcquirer extends MerchantAcquirer {
throw new RuntimeException("返回异常,做异常处理");
}
}
return bodyJsonNode;
// return bodyJsonNode;
return null;
}
......
package cn.quant.baa.pay.acquirer.weixin;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.ChannelResponse;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.config.DictionaryViewer;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.jpa.entity.PayHistoryIds;
import cn.quant.baa.pay.model.dto.DictionaryItemDTO;
import cn.quant.baa.pay.model.web.*;
import cn.quant.spring.NullException;
import cn.quant.spring.util.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
......@@ -25,13 +33,18 @@ import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
import java.util.Base64;
import java.util.UUID;
import static cn.quant.baa.pay.acquirer.AcquirerConstant.*;
/**
* Created by Administrator on 2021/8/31 0031.
*/
public class WeiXinMerchantAcquirer extends MerchantAcquirer {
private static final Logger logger = LoggerFactory.getLogger(WeiXinMerchantAcquirer.class);
private WebClient webClient;
/**
......@@ -58,9 +71,9 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
/**
* 支付初始化
* 1. 初始化私钥
* 2. 初始化平台证书
* 3. 初始化webClient
* 1. 初始化私钥
* 2. 初始化平台证书
* 3. 初始化webClient
*
* @param properties
* @return
......@@ -87,7 +100,7 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
}
@Override
public JsonNode pay(PayRequestData payRequestData, PayHistoryEntity payHistoryEntity) {
public ChannelResponse pay(PayRequestData payRequestData, PayHistoryEntity history) throws Exception {
ObjectNode bodyNode = objectMapper.createObjectNode();
// 转换金额为分
BigInteger amount = new BigDecimal(payRequestData.getAmount()).multiply(new BigDecimal(100)).toBigInteger();
......@@ -96,7 +109,7 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
.put("attach", payRequestData.getAttach())
.put("description", payRequestData.getSubject())
.put("notify_url", payRequestData.getNotifyUrl())
.put("out_trade_no", payRequestData.getOutTradeNo());
.put("out_trade_no", history.getTransactionId().toString());
bodyNode.putObject("amount")
.put("total", amount);
ObjectNode sceneInfo = objectMapper.createObjectNode()
......@@ -114,33 +127,46 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
}
bodyNode.set("scene_info", sceneInfo);
String payAccess = properties.getPayAccess();
return doExecute(payAccess, bodyNode);
ChannelResponse response = doExecute(EXECUTE_PAY, payAccess, history.getIds(), bodyNode);
JsonNode node = response.getNode();
if (node != null) {
node = response.getNode().get("h5_url");
if (node != null) {
response.setPayUrl(node.asText());
}
node = response.getNode().get("prepay_id");
if (node != null) {
response.setPrepayId(node.asText());
}
//TODO:he APP、小程序、H5、JS不同的方式设置对应的返回参数
}
return response;
}
@Override
public JsonNode checkPay(CheckPayRequestData checkPayRequestData) {
public ChannelResponse checkPay(CheckPayRequestData checkPayRequestData) throws Exception {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("mchid", properties.getPayAcctId());
String payAccess = properties.getPayAccess().replace("{out_trade_no}", checkPayRequestData.getOutTradeNo());
return doExecute(payAccess, bodyNode);
return doExecute(EXECUTE_CHECK_PAY, payAccess, null, bodyNode);
}
@Override
public JsonNode checkRefund(CheckRefundRequestData checkRefundRequestData) {
public ChannelResponse checkRefund(CheckRefundRequestData checkRefundRequestData) throws Exception {
String payAccess = properties.getPayAccess().replace("{out_refund_no}", checkRefundRequestData.getOutRefundNo());
return doExecute(payAccess, null);
return doExecute(EXECUTE_CHECK_REFUND, payAccess, null, null);
}
@Override
public JsonNode close(CloseRequestData closeRequestData) {
public ChannelResponse close(CloseRequestData closeRequestData) throws Exception {
ObjectNode bodyNode = objectMapper.createObjectNode();
bodyNode.put("mchid", properties.getPayAcctId());
String payAccess = properties.getPayAccess().replace("{out_trade_no}", closeRequestData.getOutTradeNo());
return doExecute(payAccess, bodyNode);
return doExecute(EXECUTE_CLOSE, payAccess, null, bodyNode);
}
@Override
public JsonNode refund(RefundRequestData refundRequestData) {
public ChannelResponse refund(RefundRequestData refundRequestData) throws Exception {
// 转换金额为分
BigInteger amount = new BigDecimal(refundRequestData.getRefundAmount()).multiply(new BigDecimal(100)).toBigInteger();
ObjectNode bodyNode = objectMapper.createObjectNode();
......@@ -153,18 +179,20 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
.put("total", amount)
.put("currency", "CNY");
String payAccess = properties.getPayAccess();
return doExecute(payAccess, bodyNode);
return doExecute(EXECUTE_REFUND, payAccess, null, bodyNode);
}
/**
*
* @param payAccess
* @param access
* @param bodyNode
* @return
*/
private JsonNode doExecute(String payAccess, ObjectNode bodyNode) {
private ChannelResponse doExecute(String execute, String access, PayHistoryIds ids, ObjectNode bodyNode) throws Exception {
ChannelResponse response = null;
String method = properties.getAccessMethod();
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(payAccess);
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(access);
String requestBody = "";
// 处理GET请求
if (HttpMethod.GET.name().equals(method)) {
......@@ -175,13 +203,11 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
}
} else {
// 非GET请求的时候处理requestBody
try {
if (null != bodyNode) {
requestBody = objectMapper.writeValueAsString(bodyNode);
}
} catch (JsonProcessingException e) {
e.printStackTrace();
if (null != bodyNode) {
requestBody = objectMapper.writeValueAsString(bodyNode);
}
}
String uri = uriComponentsBuilder.build().toString();
long timestamp = System.currentTimeMillis() / 1000;
......@@ -196,46 +222,117 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.exchange();
ClientResponse response = mono.block();
JsonNode bodyJsonNode = objectMapper.createObjectNode();
if (response != null) {
Mono<String> resultMono = response.bodyToMono(String.class);
String body = resultMono.block();
if (null == body) {
body = "";
}
try {
bodyJsonNode = objectMapper.readTree(body);
} catch (JsonProcessingException e) {
e.printStackTrace();
ClientResponse clientResponse = mono.block();
// if (null == body) {
// throw new NullException("http response body is null.");
// }
// if (response.statusCode().value() < 200 || response.statusCode().value() >= 300) {
// throw new HttpServerErrorException(response.statusCode());
// } else {
//
// }
// if (null == body) {
// throw new NullException("http response body is null.");
// } else {
response = response(execute, access, ids, clientResponse);
//签名信息
// String wsSignText = joining("\n", wxTimestamp, nonce, body);
// String wsSignText = String.join("\n", wxTimestamp, nonce, body);
// if (verify(wsSignText, signature)) {
//// return bodyJsonNode;
// }
// TODO: 签名校验失败,做异常处理
// throw new RuntimeException("签名校验失败");
// } else {
//// return bodyJsonNode;
// // TODO: 返回异常,做异常处理
//// throw new RuntimeException("返回异常,做异常处理");
// }
// }
// return bodyJsonNode;
return response;
}
private ChannelResponse response(ChannelResponse response) {
if (response.getSuccess()) {
} else {
DictionaryItemDTO itemDTO = DictionaryViewer.get(HTTP_STATUS_TYPE, response.getCode());
if (itemDTO == null) {
response.setCode(COMMON_ERROR_CODE);
response.setMessage(COMMON_ERROR_CODE);
} else {
response.setCode(itemDTO.getCode());
response.setMessage(itemDTO.getText());
}
}
return response;
}
if (response.statusCode().value() >= 200 && response.statusCode().value() < 300) {
//Request-ID
String requestId = response.headers().asHttpHeaders().getFirst("Request-ID");
//当前使用的微信平台证书序列号
String serial = response.headers().asHttpHeaders().getFirst("Wechatpay-Serial");
//微信服务器的时间戳
String wxTimestamp = response.headers().asHttpHeaders().getFirst("Wechatpay-Timestamp");
//微信服务器提供的随机串
String nonce = response.headers().asHttpHeaders().getFirst("Wechatpay-Nonce");
//微信平台签名
String signature = response.headers().asHttpHeaders().getFirst("Wechatpay-Signature");
//签名信息
String wsSignText = joining("\n", wxTimestamp, nonce, body);
if (verify(wsSignText, signature)) {
return bodyJsonNode;
private ChannelResponse response(String execute, String access, PayHistoryIds ids, ClientResponse response) {
if (response == null) {
throw new NullException(StringUtils.format("Client response is null : {}; {}; {};", execute, access, ids));
}
ChannelResponse responseData = new ChannelResponse();
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
//Request-ID
responseData.setRequestId(httpHeaders.getFirst("Request-ID"));
//当前使用的微信平台证书序列号
responseData.setSerial(httpHeaders.getFirst("Wechatpay-Serial"));
//微信服务器的时间戳
responseData.setTimestamp(httpHeaders.getFirst("Wechatpay-Timestamp"));
//微信服务器提供的随机串
responseData.setNonce(httpHeaders.getFirst("Wechatpay-Nonce"));
//微信平台签名
responseData.setSignature(httpHeaders.getFirst("Wechatpay-Signature"));
responseData.setSuccess(false);
Mono<String> resultMono = response.bodyToMono(String.class);
String body = resultMono.blockOptional().orElse("");
JsonNode jsonNode = null;
try {
jsonNode = objectMapper.readTree(body);
JsonNode codeNode = jsonNode.get("code");
if (codeNode == null) {
HttpStatus httpStatus = response.statusCode();
if ((EXECUTE_CLOSE.equals(execute) && httpStatus.value() == 204)) {
responseData.setSuccess(true);
responseData.setNode(jsonNode);
} else if (httpStatus.value() == 200) {
responseData.setSuccess(true);
responseData.setNode(jsonNode);
} else {
responseData.setSuccess(false);
responseData.setCode(codeNode.asText(COMMON_ERROR_CODE));
responseData.setMessage(StringUtils.format("Client response http status : {}; {}; {}; {};", execute, access, ids, httpStatus));
logger.warn(responseData.getMessage());
}
// TODO: 签名校验失败,做异常处理
throw new RuntimeException("签名校验失败");
} else {
return bodyJsonNode;
// TODO: 返回异常,做异常处理
// throw new RuntimeException("返回异常,做异常处理");
responseData.setSuccess(false);
responseData.setCode(codeNode.asText(COMMON_ERROR_CODE));
responseData.setMessage(jsonNode.get("message").asText(""));
logger.warn("Client response body code : {}; {}; {}; {};", execute, access, ids, responseData);
}
} catch (Exception e) {
logger.warn(StringUtils.format("Object mapper read response : {}; {}; {};", execute, access, ids), e);
responseData.setSuccess(false);
responseData.setCode(COMMON_ERROR_CODE);
responseData.setMessage(e.getMessage());
return responseData;
}
return bodyJsonNode;
return response(responseData);
}
/**
......@@ -284,8 +381,8 @@ public class WeiXinMerchantAcquirer extends MerchantAcquirer {
/**
* RSA验签名检查
*
* @param content 待签名数据
* @param signature 签名值
* @param content 待签名数据
* @param signature 签名值
* @return 布尔值
*/
public boolean verify(String content, String signature) {
......
......@@ -3,14 +3,13 @@ package cn.quant.baa.pay.component;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.config.DictionaryViewer;
import cn.quant.baa.pay.dict.DictType;
import cn.quant.baa.pay.model.DictionaryItem;
import cn.quant.baa.pay.model.dto.DictionaryItemDTO;
import cn.quant.baa.pay.model.web.MerchantAcquirerProperties;
import cn.quant.baa.pay.model.web.MerchantChannelResponseData;
import cn.quant.spring.NotSupportedException;
import cn.quant.spring.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.HashMap;
......@@ -50,14 +49,14 @@ public class ModelBuilder {
public Map<String, MerchantChannelResponseData> toModel(Map<String, Collection<AcquirerProperties>> profiles, String access) {
Map<String, MerchantChannelResponseData> models = new HashMap<>();
for (String code : profiles.keySet()) {
DictionaryItem item = dictionaryViewer.get(DictType.PAY, code);
DictionaryItemDTO item = dictionaryViewer.get(DictType.PAY, code);
if (item == null) {
throw new NotSupportedException(StringUtils.format("Dictionary item is null({}, {}).", DictType.PAY, code));
}
Collection<AcquirerProperties> collection = profiles.get(code);
MerchantChannelResponseData book = new MerchantChannelResponseData();
book.setCode(code);
book.setName(item.getName());
book.setName(item.getText());
book.setImageUrl(item.getImageUrl());
for (AcquirerProperties profile : collection) {
if ((access != null) && (!access.equals(profile.getAccessCode().name()))) {
......
package cn.quant.baa.pay.config;
import cn.quant.baa.pay.acquirer.AcquirerPropertiesSource;
import cn.quant.baa.pay.acquirer.AcquirerPropertiesBuilder;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.AcquirerPropertiesBuilder;
import cn.quant.baa.pay.acquirer.AcquirerPropertiesSource;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.acquirer.alipay.AlipayMerchantAcquirer;
import cn.quant.baa.pay.acquirer.weixin.WeiXinMerchantAcquirer;
import cn.quant.baa.pay.jpa.entity.*;
import cn.quant.baa.pay.jpa.repository.*;
import cn.quant.baa.pay.model.DictionaryItem;
import cn.quant.baa.pay.jpa.entity.MchChannelEntity;
import cn.quant.baa.pay.jpa.entity.PayAccountEntity;
import cn.quant.baa.pay.jpa.entity.PayAppEntity;
import cn.quant.baa.pay.jpa.entity.PayFeatureEntity;
import cn.quant.baa.pay.jpa.repository.MchChannelRepository;
import cn.quant.baa.pay.jpa.repository.PayAccountRepository;
import cn.quant.baa.pay.jpa.repository.PayAppRepository;
import cn.quant.baa.pay.jpa.repository.PayFeatureRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -65,7 +70,7 @@ public class AcquirerConfiguration {
MerchantAcquirer merchantAcquirer = MerchantAcquirer.getInstance();
Collection<AcquirerProperties> properties = acquirerPropertiesSource.getAll();
for (AcquirerProperties property : properties) {
if("WXP".equals(property.getPayChanCode())){
if ("WXP".equals(property.getPayChanCode())) {
WeiXinMerchantAcquirer acquirer = new WeiXinMerchantAcquirer();
acquirer.init(property);
merchantAcquirer.register(acquirer);
......@@ -79,5 +84,4 @@ public class AcquirerConfiguration {
}
}
package cn.quant.baa.pay.config;
import cn.quant.baa.pay.model.DictionaryItem;
import cn.quant.baa.pay.model.dto.DictionaryItemDTO;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
......@@ -12,19 +12,28 @@ import java.util.Map;
* Created by Administrator on 2021/8/23 0023.
*/
public class DictionaryViewer {
private Table<String, String, DictionaryItem> bigTable = Tables.newCustomTable(Maps.newHashMap(), new Supplier() {
public Map<String, DictionaryItem> get() {
private Table<String, String, DictionaryItemDTO> bigTable = Tables.newCustomTable(Maps.newHashMap(), new Supplier() {
public Map<String, DictionaryItemDTO> get() {
return Maps.newLinkedHashMap();
}
});
private final static DictionaryViewer viewer = new DictionaryViewer();
private DictionaryViewer() {
}
public static DictionaryViewer getInstance() {
return viewer;
}
public void add(DictionaryItem item) {
bigTable.put(item.getType(), item.getCode(), item);
public static void add(DictionaryItemDTO item) {
viewer.bigTable.put(item.getType(), item.getCode(), item);
}
public DictionaryItem get(String type, String code) {
return bigTable.get(type, code);
public static DictionaryItemDTO get(String type, String code) {
return viewer.bigTable.get(type, code);
}
......
......@@ -2,7 +2,7 @@ package cn.quant.baa.pay.config;
import cn.quant.baa.pay.jpa.entity.DictionaryEntity;
import cn.quant.baa.pay.jpa.repository.DictionaryRepository;
import cn.quant.baa.pay.model.DictionaryItem;
import cn.quant.baa.pay.model.dto.DictionaryItemDTO;
import cn.quant.spring.data.jpa.PersistentEntityInvoker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
......@@ -26,15 +26,18 @@ public class ServerConfiguration {
@Bean
public DictionaryViewer dictionaryViewer() {
DictionaryViewer dictionary = new DictionaryViewer();
DictionaryViewer dictionary = DictionaryViewer.getInstance();
List<DictionaryEntity> entities = dictionaryRepository.findAll();
for (DictionaryEntity entity : entities) {
DictionaryItem item = new DictionaryItem();
item.setName(entity.getName());
item.setCode(entity.getCode());
item.setType(entity.getType());
item.setImageUrl(entity.getImageUrl());
dictionary.add(item);
if (entity.getParentId().compareTo(0) > 0) {
DictionaryItemDTO item = new DictionaryItemDTO();
item.setCode(entity.getCode());
item.setType(entity.getType());
item.setText(entity.getText());
item.setValue(entity.getValue());
item.setImageUrl(entity.getImageUrl());
dictionary.add(item);
}
}
return dictionary;
}
......
......@@ -7,12 +7,14 @@ import cn.quant.baa.pay.jpa.entity.*;
import cn.quant.baa.pay.model.web.GoodsDetail;
import cn.quant.baa.pay.model.web.PayRequestData;
import cn.quant.spring.util.DateUtils;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import static cn.quant.baa.pay.Constant.MINI_DATE;
import static cn.quant.baa.pay.Constant.MINI_LOCAL_DATE;
/**
......@@ -20,10 +22,11 @@ import static cn.quant.baa.pay.Constant.MINI_LOCAL_DATE;
*/
public class EntityBuilder {
private static int nextTxnNo(AccountEntity account) {
public static int nextTxnNo(AccountEntity account, PayHistoryEntity history) {
Integer txnNo = account.getNextTxnNo();
account.setTxnNo(txnNo);
account.setNextTxnNo(txnNo + 1);
history.setTxnNo(txnNo);
return txnNo;
}
......@@ -60,7 +63,7 @@ public class EntityBuilder {
return account;
}
public static PayHistoryEntity history(AccountEntity account, PayHistoryIds ids, long historyId, PayRequestData data, AcquirerProperties profile
public static PayHistoryEntity payHistory(AccountEntity account, PayHistoryIds ids, long historyId, PayRequestData data, AcquirerProperties profile
, TransactionSession session) {
BigDecimal discount = new BigDecimal(data.getDiscounts());
......@@ -70,11 +73,9 @@ public class EntityBuilder {
BigDecimal amount = new BigDecimal(data.getAmount());
String signer = data.getGoodsSigner();
Long accountId = account.getAccountId();
PayHistoryEntity entity = new PayHistoryEntity();
entity.setIds(ids);
entity.setAccountId(accountId);
entity.setAccountId(account.getAccountId());
entity.setAddress(data.getAddress());
entity.setAttachText(data.getAttach());
entity.setCreditDebitFlag(CreditDebitFlag.C);
......@@ -99,15 +100,14 @@ public class EntityBuilder {
entity.setRequestTime(session.getRequestTime());
entity.setShopName(data.getShopName());
entity.setStatementeFlag(true);
entity.setStatisticsCode("RPAY");
entity.setStatisticsCode("PYMT");
entity.setStatusCode(StatusCode.PEND);
entity.setSubject(data.getSubject());
entity.setTransactionId(historyId);
entity.setTxnAmount(amount);
entity.setTxnDate(session.getBusinessLocalDate());
entity.setTxnTime(session.getBusinessLocalTime());
entity.setTxnType("RETL");
entity.setTxnNo(nextTxnNo(account));
entity.setTxnType("PYMT");
if (cash.compareTo(BigDecimal.ZERO) > 0) {
entity.setTxnCode("R001");
} else {
......@@ -139,4 +139,17 @@ public class EntityBuilder {
return entity;
}
public static BatchCycleTriggerEntity payTrigger(Long triggerId, PayHistoryEntity history){
Date now = DateUtils.now();
BatchCycleTriggerEntity entity = new BatchCycleTriggerEntity();
entity.setAccountId(history.getAccountId());
entity.setChanNotifyStatus(StatusCode.PEND);
entity.setEntityCode(history.getTxnType());
entity.setMchNotifyStatus(StatusCode.PEND);
entity.setPayDueTime(DateUtils.toLocalDateTime(now).plusMinutes(30));
entity.setTargetId(history.getTransactionId());
entity.setTriggerId(triggerId);
entity.setPartitionKey(history.getPartitionKey());
return entity;
}
}
......@@ -63,7 +63,6 @@ public class AccountIds extends PrimaryIds implements Serializable {
final StringBuilder sb = new StringBuilder("AccountIds{");
sb.append("institutionId='").append(institutionId).append('\'');
sb.append(", accountRefNo='").append(accountRefNo).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
package cn.quant.baa.pay.jpa.entity;
import cn.quant.baa.pay.dict.StatusCode;
import cn.quant.spring.data.jpa.entity.PartitionEntity;
import cn.quant.spring.util.StringUtils;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* Created by Administrator on 2021/9/22 0022.
*/
@Entity
@Table(name = "batch_cycle_trigger")
public class BatchCycleTriggerEntity extends PartitionEntity implements Serializable {
private static final long serialVersionUID = 1419514603248200095L;
public final static String CLASS_NAME = BatchCycleTriggerEntity.class.getSimpleName();
@Id
@Column(name = "TRIGGER_ID", nullable = false)
private long triggerId;
@Column(name = "ENTITY_CODE", nullable = false, length = 4)
private String entityCode;
@Column(name = "TARGET_ID", nullable = false)
private Long targetId;
@Column(name = "ACCOUNT_ID", nullable = false)
private Long accountId;
@Column(name = "PAY_DUE_TIME", nullable = false)
private LocalDateTime payDueTime;
@Enumerated(EnumType.STRING)
@Column(name = "CHAN_NOTIFY_STATUS", nullable = false, length = 4)
private StatusCode chanNotifyStatus;
@Column(name = "CHAN_NOTIFY_TIME", nullable = true)
private Date chanNotifyTime;
@Enumerated(EnumType.STRING)
@Column(name = "MCH_NOTIFY_STATUS", nullable = false, length = 4)
private StatusCode mchNotifyStatus;
@Column(name = "MCH_NOTIFY_TIME", nullable = true)
private Date mchNotifyTime;
public long getTriggerId() {
return triggerId;
}
public void setTriggerId(long triggerId) {
this.triggerId = triggerId;
}
public String getEntityCode() {
return entityCode;
}
public void setEntityCode(String entityCode) {
this.entityCode = entityCode;
}
public Long getTargetId() {
return targetId;
}
public void setTargetId(Long targetId) {
this.targetId = targetId;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public LocalDateTime getPayDueTime() {
return payDueTime;
}
public void setPayDueTime(LocalDateTime payDueTime) {
this.payDueTime = payDueTime;
}
public StatusCode getChanNotifyStatus() {
return chanNotifyStatus;
}
public void setChanNotifyStatus(StatusCode chanNotifyStatus) {
this.chanNotifyStatus = chanNotifyStatus;
}
public Date getChanNotifyTime() {
return chanNotifyTime;
}
public void setChanNotifyTime(Date chanNotifyTime) {
this.chanNotifyTime = chanNotifyTime;
}
public StatusCode getMchNotifyStatus() {
return mchNotifyStatus;
}
public void setMchNotifyStatus(StatusCode mchNotifyStatus) {
this.mchNotifyStatus = mchNotifyStatus;
}
public Date getMchNotifyTime() {
return mchNotifyTime;
}
public void setMchNotifyTime(Date mchNotifyTime) {
this.mchNotifyTime = mchNotifyTime;
}
@Override
public String getPersistentKey() {
return StringUtils.toDelimitedString(CLASS_NAME, triggerId);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BatchCycleTriggerEntity that = (BatchCycleTriggerEntity) o;
return triggerId == that.triggerId;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("BatchCycleTriggerEntity{");
sb.append("triggerId=").append(triggerId);
sb.append(", entityCode='").append(entityCode).append('\'');
sb.append(", targetId=").append(targetId);
sb.append(", accountId=").append(accountId);
sb.append(", payDueTime=").append(payDueTime);
sb.append(", chanNotifyStatus='").append(chanNotifyStatus).append('\'');
sb.append(", chanNotifyTime=").append(chanNotifyTime);
sb.append(", mchNotifyStatus='").append(mchNotifyStatus).append('\'');
sb.append(", mchNotifyTime=").append(mchNotifyTime);
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
}
package cn.quant.baa.pay.jpa.entity;
import cn.quant.baa.pay.dict.DictType;
import cn.quant.spring.data.jpa.entity.OptimisticEntity;
import javax.persistence.Column;
......@@ -21,12 +20,21 @@ public class DictionaryEntity extends OptimisticEntity implements Serializable {
@EmbeddedId
private DictionaryIds ids;
@Column(name = "NAME", nullable = false, length = 255)
private String name;
@Column(name = "ID", nullable = false, updatable = false)
private Long id;
@Column(name = "TEXT", nullable = false, length = 64)
private String text;
@Column(name = "VALUE", nullable = false, length = 500)
private String value;
@Column(name = "IMAGE_URL", nullable = true, length = 500)
private String imageUrl;
@Column(name = "PARENT_ID", nullable = true, length = 500)
private Integer parentId;
public DictionaryIds getIds() {
return ids;
}
......@@ -35,12 +43,28 @@ public class DictionaryEntity extends OptimisticEntity implements Serializable {
this.ids = ids;
}
public String getName() {
return name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public void setName(String name) {
this.name = name;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getImageUrl() {
......@@ -51,6 +75,14 @@ public class DictionaryEntity extends OptimisticEntity implements Serializable {
this.imageUrl = imageUrl;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
@Override
public String getPersistentKey() {
return ids.getPersistentKey();
......@@ -68,8 +100,11 @@ public class DictionaryEntity extends OptimisticEntity implements Serializable {
public String toString() {
final StringBuilder sb = new StringBuilder("DictionaryEntity{");
sb.append("ids=").append(ids);
sb.append(", name='").append(name).append('\'');
sb.append(", id=").append(id);
sb.append(", text='").append(text).append('\'');
sb.append(", value='").append(value).append('\'');
sb.append(", imageUrl='").append(imageUrl).append('\'');
sb.append(", parentId=").append(parentId);
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
......@@ -82,4 +117,6 @@ public class DictionaryEntity extends OptimisticEntity implements Serializable {
public String getCode(){
return ids.getCode();
}
}
......@@ -18,10 +18,10 @@ public class DictionaryIds extends PrimaryIds implements Serializable {
private final static String CLASS_NAME = DictionaryEntity.class.getSimpleName();
@Column(name = "TYPE", nullable = false, updatable = false, length = 4)
@Column(name = "TYPE", nullable = false, updatable = false, length = 32)
private String type;
@Column(name = "CODE", nullable = false, updatable = false, length = 4)
@Column(name = "CODE", nullable = false, updatable = false, length = 32)
private String code;
public String getType() {
......@@ -64,7 +64,6 @@ public class DictionaryIds extends PrimaryIds implements Serializable {
final StringBuilder sb = new StringBuilder("DictionaryIds{");
sb.append("type='").append(type).append('\'');
sb.append(", code='").append(code).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
......@@ -64,7 +64,6 @@ public class PayAccountIds extends PrimaryIds implements Serializable {
final StringBuilder sb = new StringBuilder("PayAccountIds{");
sb.append("payChanCode='").append(payChanCode).append('\'');
sb.append(", payAcctId='").append(payAcctId).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
......@@ -68,7 +68,6 @@ public class PayFeatureIds extends PrimaryIds implements Serializable {
final StringBuilder sb = new StringBuilder("PayFeatureIds{");
sb.append("payChanCode='").append(payChanCode).append('\'');
sb.append(", accessCode='").append(accessCode).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
......@@ -75,7 +75,6 @@ public class PayHistoryIds extends PrimaryIds implements Serializable {
sb.append("institutionId='").append(institutionId).append('\'');
sb.append(", productId='").append(productId).append('\'');
sb.append(", externalOrderNo='").append(externalOrderNo).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
package cn.quant.baa.pay.jpa.entity;
import cn.quant.baa.pay.dict.StatusCode;
import cn.quant.spring.data.jpa.entity.DescriptionEntity;
import org.hibernate.annotations.Type;
......@@ -35,13 +36,13 @@ public class StatusCodeEntity extends DescriptionEntity {
private Boolean sendNoticeFlag;
@Column(name = "REGR_CODE", nullable = true, length = 4)
private String regrCode;
private StatusCode regrCode;
@Column(name = "FAILED_CODE", nullable = false, length = 4)
private String failedCode;
private StatusCode failedCode;
@Column(name = "NEXT_CODE", nullable = true, length = 4)
private String nextCode;
private StatusCode nextCode;
@Column(name = "MESSAGE_CODE", nullable = true, length = 4)
private String messageCode;
......@@ -86,27 +87,27 @@ public class StatusCodeEntity extends DescriptionEntity {
this.sendNoticeFlag = sendNoticeFlag;
}
public String getRegrCode() {
public StatusCode getRegrCode() {
return regrCode;
}
public void setRegrCode(String regrCode) {
public void setRegrCode(StatusCode regrCode) {
this.regrCode = regrCode;
}
public String getFailedCode() {
public StatusCode getFailedCode() {
return failedCode;
}
public void setFailedCode(String failedCode) {
public void setFailedCode(StatusCode failedCode) {
this.failedCode = failedCode;
}
public String getNextCode() {
public StatusCode getNextCode() {
return nextCode;
}
public void setNextCode(String nextCode) {
public void setNextCode(StatusCode nextCode) {
this.nextCode = nextCode;
}
......@@ -126,7 +127,7 @@ public class StatusCodeEntity extends DescriptionEntity {
return this.ids.getEntity();
}
public String getCode(){
public StatusCode getCode(){
return this.ids.getCode();
}
......
package cn.quant.baa.pay.jpa.entity;
import cn.quant.baa.pay.dict.StatusCode;
import cn.quant.spring.data.jpa.entity.PrimaryIds;
import cn.quant.spring.util.StringUtils;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import java.io.Serializable;
import java.util.Objects;
......@@ -23,8 +26,9 @@ public class StatusCodeIds extends PrimaryIds implements Serializable {
@Column(name = "ENTITY", nullable = false, updatable = false, length = 4)
private String entity;
@Enumerated(EnumType.STRING)
@Column(name = "CODE", nullable = false, updatable = false, length = 4)
private String code;
private StatusCode code;
public String getInstitutionId() {
return institutionId;
......@@ -42,11 +46,11 @@ public class StatusCodeIds extends PrimaryIds implements Serializable {
this.entity = entity;
}
public String getCode() {
public StatusCode getCode() {
return code;
}
public void setCode(String code) {
public void setCode(StatusCode code) {
this.code = code;
}
......@@ -76,7 +80,6 @@ public class StatusCodeIds extends PrimaryIds implements Serializable {
sb.append("institutionId='").append(institutionId).append('\'');
sb.append(", entity='").append(entity).append('\'');
sb.append(", code='").append(code).append('\'');
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
......
package cn.quant.baa.pay.jpa.repository;
import cn.quant.baa.pay.jpa.entity.BatchCycleTriggerEntity;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.jpa.entity.PayHistoryIds;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* Created by Administrator on 2021/8/22 0022.
*/
@Repository
public interface BatchCycleTriggerRepository extends JpaRepository<BatchCycleTriggerEntity, Long> {
}
package cn.quant.baa.pay.model;
package cn.quant.baa.pay.model.dto;
import java.io.Serializable;
/**
* Created by Administrator on 2021/8/23 0023.
*/
public class DictionaryItem implements Serializable {
public class DictionaryItemDTO implements Serializable {
private static final long serialVersionUID = -1385949230287727125L;
private Long id;
private Long parentId;
private String type;
private String code;
private String name;
private String text;
private String value;
private String imageUrl;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getType() {
return type;
}
......@@ -31,12 +54,20 @@ public class DictionaryItem implements Serializable {
this.code = code;
}
public String getName() {
return name;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getValue() {
return value;
}
public void setName(String name) {
this.name = name;
public void setValue(String value) {
this.value = value;
}
public String getImageUrl() {
......@@ -49,10 +80,13 @@ public class DictionaryItem implements Serializable {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("DictionaryItem{");
sb.append("type='").append(type).append('\'');
final StringBuilder sb = new StringBuilder("DictionaryItemDTO{");
sb.append("id=").append(id);
sb.append(", parentId=").append(parentId);
sb.append(", type='").append(type).append('\'');
sb.append(", code='").append(code).append('\'');
sb.append(", name='").append(name).append('\'');
sb.append(", text='").append(text).append('\'');
sb.append(", value='").append(value).append('\'');
sb.append(", imageUrl='").append(imageUrl).append('\'');
sb.append('}');
return sb.toString();
......
package cn.quant.baa.pay.model;
package cn.quant.baa.pay.model.dto;
import cn.quant.baa.pay.dict.StatusCode;
import cn.quant.spring.data.jpa.PersistentObject;
import java.io.Serializable;
......@@ -7,18 +8,18 @@ import java.io.Serializable;
/**
* Created by Administrator on 2021/9/13 0013.
*/
public class StatusCode implements PersistentObject, Serializable {
public class StatusCodeDTO implements PersistentObject, Serializable {
private static final long serialVersionUID = 952357481570545998L;
private String institutionId;
private String entity;
private String code;
private StatusCode code;
private Integer priority;
private String codeType;
private String postingCode;
private Boolean sendNoticeFlag;
private String regrCode;
private String failedCode;
private String nextCode;
private StatusCode regrCode;
private StatusCode failedCode;
private StatusCode nextCode;
private String messageCode;
public String getInstitutionId() {
......@@ -37,11 +38,11 @@ public class StatusCode implements PersistentObject, Serializable {
this.entity = entity;
}
public String getCode() {
public StatusCode getCode() {
return code;
}
public void setCode(String code) {
public void setCode(StatusCode code) {
this.code = code;
}
......@@ -77,27 +78,27 @@ public class StatusCode implements PersistentObject, Serializable {
this.sendNoticeFlag = sendNoticeFlag;
}
public String getRegrCode() {
public StatusCode getRegrCode() {
return regrCode;
}
public void setRegrCode(String regrCode) {
public void setRegrCode(StatusCode regrCode) {
this.regrCode = regrCode;
}
public String getFailedCode() {
public StatusCode getFailedCode() {
return failedCode;
}
public void setFailedCode(String failedCode) {
public void setFailedCode(StatusCode failedCode) {
this.failedCode = failedCode;
}
public String getNextCode() {
public StatusCode getNextCode() {
return nextCode;
}
public void setNextCode(String nextCode) {
public void setNextCode(StatusCode nextCode) {
this.nextCode = nextCode;
}
......@@ -111,7 +112,7 @@ public class StatusCode implements PersistentObject, Serializable {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("StatusCode{");
final StringBuilder sb = new StringBuilder("StatusCodeDTO{");
sb.append("institutionId='").append(institutionId).append('\'');
sb.append(", entity='").append(entity).append('\'');
sb.append(", code='").append(code).append('\'');
......
......@@ -3,7 +3,7 @@ package cn.quant.baa.pay.service;
import cn.quant.baa.pay.config.LocalCacheConfiguration;
import cn.quant.baa.pay.jpa.entity.StatusCodeEntity;
import cn.quant.baa.pay.jpa.entity.StatusCodeIds;
import cn.quant.baa.pay.model.StatusCode;
import cn.quant.baa.pay.model.dto.StatusCodeDTO;
import cn.quant.spring.data.jpa.PersistentEntityInvoker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
......@@ -21,8 +21,8 @@ public class ProfileStorageService {
@Cacheable(cacheManager = LocalCacheConfiguration.LOCAL_CACHE_MANAGER
, cacheNames = LocalCacheConfiguration.LOCAL_CACHE_PROFILE
, key = "#ids.persistentKey")
public StatusCode getStatusCode(StatusCodeIds ids) throws Exception {
StatusCode code = persistentEntityInvoker.Invoke(ids, StatusCodeEntity.class, StatusCode.class);
public StatusCodeDTO getStatusCode(StatusCodeIds ids) throws Exception {
StatusCodeDTO code = persistentEntityInvoker.Invoke(ids, StatusCodeEntity.class, StatusCodeDTO.class);
return code;
}
......
package cn.quant.baa.pay.rest;
import cn.quant.baa.pay.jpa.entity.StatusCodeIds;
import cn.quant.baa.pay.model.StatusCode;
import cn.quant.baa.pay.model.web.MerchantAcquirerProperties;
import cn.quant.baa.pay.model.web.MerchantChannelResponseData;
import cn.quant.baa.pay.model.web.MerchantChannelRequestData;
......@@ -35,10 +33,13 @@ public class MerchantController extends AbstractController {
@Autowired
private CacheManager cacheManager;
@Autowired
private ProfileStorageService profileStorageService;
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/list")
public ResponseEntity list(@RequestBody BusinessRequest<MerchantChannelRequestData> request) {
public ResponseEntity list(@RequestBody BusinessRequest<MerchantChannelRequestData> request) throws Exception {
TransactionSession session = TransactionSession.session();
String requestId = session.getRequestId();
......
package cn.quant.baa.pay.rest;
import cn.quant.baa.pay.annotation.BusinessMapping;
import cn.quant.baa.pay.component.Sequencer;
import cn.quant.baa.pay.context.TransactionSession;
import cn.quant.baa.pay.model.BusinessRequest;
import cn.quant.baa.pay.model.web.CheckPayRequestData;
import cn.quant.baa.pay.model.web.CheckRefundRequestData;
import cn.quant.baa.pay.model.web.PayRequestData;
import cn.quant.baa.pay.service.TransactionService;
import cn.quant.spring.context.ServerApplicationContext;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* Author: Lipeng Liu
* Date: 2021/9/9
* Time: 上午9:51
* Description: No Description
*/
@Controller
//@RestController
@RequestMapping("pay")
public class PayTestController {
ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private TransactionService transactionService;
@Autowired
private ServerApplicationContext serverApplicationContext;
@Autowired
private Sequencer sequencer;
@GetMapping("")
public String getPay(Model model) {
return "pay/index";
}
@RequestMapping("h5")
public String getH5(Model model) {
return "pay/h5";
}
@RequestMapping("checkPay")
public String checkPay(CheckPayRequestData data, Model model, HttpServletRequest servletRequest) {
String res = "";
if (servletRequest.getMethod().equals("POST")) {
res = transactionService.checkPay(data).toString();
}
model.addAttribute("res", res);
return "pay/checkPay";
}
@RequestMapping("checkRefund")
public String checkRefund(CheckRefundRequestData data, Model model, HttpServletRequest servletRequest) {
String res = "";
if (servletRequest.getMethod().equals("POST")) {
res = transactionService.checkRefund(data).toString();
}
model.addAttribute("res", res);
return "pay/checkRefund";
}
@PostMapping("goPay")
@BusinessMapping(session = 1)
@ResponseBody
public JsonNode goPay(@RequestBody(required = false) BusinessRequest<PayRequestData> requestData) {
PayRequestData data = requestData.getData();
String str = "{\"subject\":\"测试订单1\",\"mchId\":\"wx2f44c7fe7b08458d\",\"chanId\":\"75772285618946307\",\"outTradeNo\":\"11111111223\",\"originalAmount\":\"110.00\",\"amount\":0.01,\"discounts\":\"10.00\",\"notifyUrl\":\"http://127.0.0.1:8080/notifyUrl\",\"buyerId\":\"777777\",\"attach\":\"AAAA-BBBB-1111-2222\",\"creditAmount\":\"10.00\",\"cashAmount\":\"10\",\"goodsDetail\":[{\"goodsNo\":\"123123\",\"goodsId\":\"11111\",\"goodsName\":\"商品1\",\"quantity\":2,\"price\":\"10.00\",\"discounts\":\"2.5\",\"amount\":\"17.5\",\"attach\":\"---\",\"creditAmount\":123,\"cashAmount\":123}]}";
try {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
PayRequestData payRequestData = objectMapper.readValue(str, PayRequestData.class);
String[] temp = data.getChanId().split("_");
payRequestData.setChanId(temp[0]);
payRequestData.setMchId(temp[1]);
payRequestData.setOutTradeNo(data.getOutTradeNo());
payRequestData.setSubject(data.getSubject());
payRequestData.setAmount(data.getAmount());
payRequestData.setNotifyUrl("http://127.0.0.1:8080/notifyUrl");
JsonNode res = transactionService.pay(payRequestData);
return res;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return objectMapper.createObjectNode();
}
}
\ No newline at end of file
//package cn.quant.baa.pay.rest;
//
//import cn.quant.baa.pay.annotation.BusinessMapping;
//import cn.quant.baa.pay.component.Sequencer;
//import cn.quant.baa.pay.context.TransactionSession;
//import cn.quant.baa.pay.model.BusinessRequest;
//import cn.quant.baa.pay.model.web.CheckPayRequestData;
//import cn.quant.baa.pay.model.web.CheckRefundRequestData;
//import cn.quant.baa.pay.model.web.PayRequestData;
//import cn.quant.baa.pay.service.TransactionService;
//import cn.quant.spring.context.ServerApplicationContext;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.DeserializationFeature;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.databind.PropertyNamingStrategy;
//import com.fasterxml.jackson.databind.json.JsonMapper;
//import com.fasterxml.jackson.databind.node.ObjectNode;
//import org.json.JSONObject;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Controller;
//import org.springframework.ui.Model;
//import org.springframework.web.bind.annotation.*;
//
//import javax.servlet.http.HttpServletRequest;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * Created with IntelliJ IDEA.
// * Author: Lipeng Liu
// * Date: 2021/9/9
// * Time: 上午9:51
// * Description: No Description
// */
//@Controller
////@RestController
//@RequestMapping("pay")
//public class PayTestController {
//
// ObjectMapper objectMapper = new ObjectMapper();
//
// @Autowired
// private TransactionService transactionService;
//
// @Autowired
// private ServerApplicationContext serverApplicationContext;
//
// @Autowired
// private Sequencer sequencer;
//
// @GetMapping("")
// public String getPay(Model model) {
// return "pay/index";
// }
//
// @RequestMapping("h5")
// public String getH5(Model model) {
// return "pay/h5";
// }
//
// @RequestMapping("checkPay")
// public String checkPay(CheckPayRequestData data, Model model, HttpServletRequest servletRequest) {
// String res = "";
// if (servletRequest.getMethod().equals("POST")) {
// res = transactionService.checkPay(data).toString();
// }
// model.addAttribute("res", res);
// return "pay/checkPay";
// }
//
// @RequestMapping("checkRefund")
// public String checkRefund(CheckRefundRequestData data, Model model, HttpServletRequest servletRequest) {
//
// String res = "";
// if (servletRequest.getMethod().equals("POST")) {
// res = transactionService.checkRefund(data).toString();
// }
// model.addAttribute("res", res);
// return "pay/checkRefund";
// }
//
//
// @PostMapping("goPay")
// @BusinessMapping(session = 1)
// @ResponseBody
// public JsonNode goPay(@RequestBody(required = false) BusinessRequest<PayRequestData> requestData) {
// PayRequestData data = requestData.getData();
// String str = "{\"subject\":\"测试订单1\",\"mchId\":\"wx2f44c7fe7b08458d\",\"chanId\":\"75772285618946307\",\"outTradeNo\":\"11111111223\",\"originalAmount\":\"110.00\",\"amount\":0.01,\"discounts\":\"10.00\",\"notifyUrl\":\"http://127.0.0.1:8080/notifyUrl\",\"buyerId\":\"777777\",\"attach\":\"AAAA-BBBB-1111-2222\",\"creditAmount\":\"10.00\",\"cashAmount\":\"10\",\"goodsDetail\":[{\"goodsNo\":\"123123\",\"goodsId\":\"11111\",\"goodsName\":\"商品1\",\"quantity\":2,\"price\":\"10.00\",\"discounts\":\"2.5\",\"amount\":\"17.5\",\"attach\":\"---\",\"creditAmount\":123,\"cashAmount\":123}]}";
// try {
// objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// PayRequestData payRequestData = objectMapper.readValue(str, PayRequestData.class);
// String[] temp = data.getChanId().split("_");
// payRequestData.setChanId(temp[0]);
// payRequestData.setMchId(temp[1]);
// payRequestData.setOutTradeNo(data.getOutTradeNo());
// payRequestData.setSubject(data.getSubject());
// payRequestData.setAmount(data.getAmount());
// payRequestData.setNotifyUrl("http://127.0.0.1:8080/notifyUrl");
// JsonNode res = transactionService.pay(payRequestData);
// return res;
// } catch (JsonProcessingException e) {
// e.printStackTrace();
// }
// return objectMapper.createObjectNode();
// }
//
//}
\ No newline at end of file
package cn.quant.baa.pay.rest;
import cn.quant.baa.pay.acquirer.ChannelResponse;
import cn.quant.baa.pay.annotation.BusinessMapping;
import cn.quant.baa.pay.jpa.entity.PayHistoryEntity;
import cn.quant.baa.pay.model.BusinessRequest;
import cn.quant.baa.pay.model.web.*;
import cn.quant.baa.pay.service.TransactionService;
import com.fasterxml.jackson.databind.JsonNode;
import cn.quant.spring.http.HttpResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
......@@ -23,61 +23,79 @@ public class TransactionController extends BusinessController {
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/pay")
public JsonNode pay(@RequestBody BusinessRequest<PayRequestData> request) {
public ResponseEntity pay(@RequestBody BusinessRequest<PayRequestData> request) {
PayRequestData data = request.getData();
JsonNode res = transactionService.pay(data);
PayRequestData requestData = request.getData();
ChannelResponse responseData = null;
try {
responseData = transactionService.pay(requestData);
} catch (Exception e) {
e.printStackTrace();
}
System.currentTimeMillis();
return res;
ResponseEntity<HttpResponseData> responseEntity = succeed(responseData);
return responseEntity;
}
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/checkPay")
public JsonNode checkPay(@RequestBody BusinessRequest<CheckPayRequestData> request) {
public ChannelResponse checkPay(@RequestBody BusinessRequest<CheckPayRequestData> request) throws Exception {
CheckPayRequestData data = request.getData();
JsonNode res = transactionService.checkPay(data);
ChannelResponse responseData = null;
responseData = transactionService.checkPay(data);
System.currentTimeMillis();
return res;
return responseData;
}
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/checkRefund")
public JsonNode checkRefund(@RequestBody BusinessRequest<CheckRefundRequestData> request) {
public ChannelResponse checkRefund(@RequestBody BusinessRequest<CheckRefundRequestData> request) throws Exception {
CheckRefundRequestData data = request.getData();
JsonNode res = transactionService.checkRefund(data);
ChannelResponse responseData = null;
responseData = transactionService.checkRefund(data);
System.currentTimeMillis();
return res;
return responseData;
}
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/close")
public JsonNode close(@RequestBody BusinessRequest<CloseRequestData> request) {
public ChannelResponse close(@RequestBody BusinessRequest<CloseRequestData> request) throws Exception {
CloseRequestData data = request.getData();
JsonNode res = transactionService.close(data);
ChannelResponse responseData = null;
responseData = transactionService.close(data);
System.currentTimeMillis();
return res;
return responseData;
}
@ResponseBody
@BusinessMapping(session = 1)
@PostMapping("/refund")
public JsonNode refund(@RequestBody BusinessRequest<RefundRequestData> request) {
public ChannelResponse refund(@RequestBody BusinessRequest<RefundRequestData> request) throws Exception {
RefundRequestData data = request.getData();
JsonNode res = transactionService.refund(data);
ChannelResponse responseData = null;
responseData = transactionService.refund(data);
System.currentTimeMillis();
return res;
return responseData;
}
}
......@@ -2,13 +2,14 @@ package cn.quant.baa.pay.service;
import cn.quant.baa.pay.acquirer.AcquirerPropertiesSource;
import cn.quant.baa.pay.acquirer.AcquirerProperties;
import cn.quant.baa.pay.acquirer.ChannelResponse;
import cn.quant.baa.pay.acquirer.MerchantAcquirer;
import cn.quant.baa.pay.config.DictionaryViewer;
import cn.quant.baa.pay.context.TransactionSession;
import cn.quant.baa.pay.jpa.EntityBuilder;
import cn.quant.baa.pay.jpa.entity.*;
import cn.quant.baa.pay.model.web.*;
import cn.quant.baa.pay.util.AssertUtils;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -35,6 +36,9 @@ public class TransactionService extends BusinessService {
@Autowired
private MerchantAcquirer acquirer;
@Autowired
private DictionaryViewer dictionaryViewer;
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void check(PayHistoryIds ids, TransactionSession session) {
PayHistoryEntity historyEntity = session.findOne(PayHistoryEntity.class, ids);
......@@ -43,8 +47,8 @@ public class TransactionService extends BusinessService {
}
}
@Transactional
public TransactionSession payHistory(PayRequestData data) {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public ChannelResponse pay(PayRequestData data) throws Exception {
validate(data);
......@@ -57,10 +61,21 @@ public class TransactionService extends BusinessService {
String institutionId = profile.getInstitutionId();
String productId = profile.getProductId();
String buyerId = data.getBuyerId();
TransactionSession session = TransactionSession.session();
String outTradeNo = data.getOutTradeNo();
PayHistoryIds ids = new PayHistoryIds();
ids.setInstitutionId(institutionId);
ids.setProductId(productId);
ids.setExternalOrderNo(outTradeNo);
check(ids, session);
prepare(institutionId, productId, buyerId, session);
String mchId = data.getMchId();
if (!mchId.equals(profile.getPayAppId())) {
AssertUtils.throwMessage(ACQUIRER_NOMATCH, chanId, mchId);
}
AccountEntity account = session.getAccount();
long historyId = session.nextId();
......@@ -75,60 +90,59 @@ public class TransactionService extends BusinessService {
details.add(detailEntity);
}
PayHistoryEntity history = EntityBuilder.payHistory(account, ids, historyId, data, profile, session);
String mchId = data.getMchId();
if (!mchId.equals(profile.getPayAppId())) {
AssertUtils.throwMessage(ACQUIRER_NOMATCH, chanId, mchId);
}
long triggerId = session.nextId();
ChannelResponse responseData = acquirer.pay(data, history);
String outTradeNo = data.getOutTradeNo();
PayHistoryIds ids = new PayHistoryIds();
ids.setInstitutionId(institutionId);
ids.setProductId(productId);
ids.setExternalOrderNo(outTradeNo);
check(ids, session);
if(responseData.getSuccess()){
EntityBuilder.nextTxnNo(account, history);
BatchCycleTriggerEntity trigger = EntityBuilder.payTrigger(triggerId, history);
session.pushEntity(history);
session.pushEntity(trigger);
session.pushEntity(details);
PayHistoryEntity history = EntityBuilder.history(account, ids, historyId, data, profile, session);
session.pushEntity(history);
session.pushEntity(details);
session.commit();
session.commit();
session.addProperty(PayHistoryEntity.class, history);
session.addProperty(PayGoodsDetailEntity.class, details);
session.addProperty(PayHistoryEntity.class, history);
session.addProperty(PayGoodsDetailEntity.class, details);
}
return session;
return responseData;
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public JsonNode pay(PayRequestData data) {
TransactionSession session = payHistory(data);
PayHistoryEntity payHistoryEntity = session.getProperty(PayHistoryEntity.class, PayHistoryEntity.class);
System.currentTimeMillis();
return acquirer.pay(data, payHistoryEntity);
}
// @Transactional(propagation = Propagation.NOT_SUPPORTED)
// public JsonNode pay(PayRequestData data) {
//
//
//
// TransactionSession session = payHistory(data);
//
// PayHistoryEntity payHistoryEntity = session.getProperty(PayHistoryEntity.class, PayHistoryEntity.class);
// System.currentTimeMillis();
// return acquirer.pay(data, payHistoryEntity);
// }
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public JsonNode checkPay(CheckPayRequestData data) {
public ChannelResponse checkPay(CheckPayRequestData data) throws Exception {
return acquirer.checkPay(data);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public JsonNode checkRefund(CheckRefundRequestData data) {
public ChannelResponse checkRefund(CheckRefundRequestData data) throws Exception {
return acquirer.checkRefund(data);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public JsonNode close(CloseRequestData data) {
public ChannelResponse close(CloseRequestData data) throws Exception {
return acquirer.close(data);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public JsonNode refund(RefundRequestData data) {
public ChannelResponse refund(RefundRequestData data) throws Exception {
return acquirer.refund(data);
}
......
......@@ -27,7 +27,7 @@
</encoder>
</appender>
<logger name="cn.quant.baa.pay" level="ERROR"/>
<logger name="cn.quant.baa.pay" level="WARN"/>
<logger name="javax.activation" level="ERROR"/>
<logger name="org.quartz.core" level="ERROR"/>
<logger name="org.quartz.simpl" level="ERROR"/>
......
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