Alipay-HK 创建订单和异步回调
This commit is contained in:
6
pom.xml
6
pom.xml
@@ -226,6 +226,12 @@
|
||||
<version>2.17.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.stripe</groupId>
|
||||
<artifactId>stripe-java</artifactId>
|
||||
<version>25.0.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ai.da.common.constant;
|
||||
|
||||
public class AlipayHKConstant {
|
||||
|
||||
// 服务名
|
||||
public static final String CREATE_ORDER = "create_order";
|
||||
public static final String ORDER_DETAILS = "order_details";
|
||||
public static final String TRANSACTION_DETAILS = "transaction_details";
|
||||
public static final String GET_FILE = "get_file";
|
||||
public static final String CREATE_AUTO_DEBIT = "create_auto_debit";
|
||||
public static final String REFRESH_TRANSACTION_STATUS = "refresh_transaction_status";
|
||||
public static final String REFUND_TRANSACTION = "refund_transaction";
|
||||
|
||||
// 订单状态
|
||||
public static final String STATUS_NEW = "new";
|
||||
public static final String STATUS_WAIT = "wait";
|
||||
public static final String STATUS_PAID = "paid";
|
||||
public static final String STATUS_EXPIRED = "expired";
|
||||
public static final String STATUS_LIQUIDATED = "liquidated";
|
||||
}
|
||||
@@ -19,7 +19,12 @@ public enum PayTypeEnum {
|
||||
/**
|
||||
* PayPal
|
||||
*/
|
||||
PAYPAL("PayPal");
|
||||
PAYPAL("PayPal"),
|
||||
|
||||
/**
|
||||
* 香港支付宝
|
||||
*/
|
||||
ALIPAY_HK("Alipay-HK");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
|
||||
@@ -49,7 +49,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew",
|
||||
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
|
||||
// "/api/python/chatStream",
|
||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back"
|
||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify"
|
||||
);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,9 +6,16 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||||
import org.bouncycastle.crypto.signers.RSADigestSigner;
|
||||
import org.bouncycastle.crypto.util.PublicKeyFactory;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.util.io.pem.PemObject;
|
||||
import org.bouncycastle.util.io.pem.PemReader;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
@@ -25,22 +32,24 @@ import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AlipayHKEncryptionUtil {
|
||||
|
||||
@Value("${alipay.hk.merchant-id}")
|
||||
private static String merchantId;
|
||||
@Value("${alipayHK.merchantId}")
|
||||
private String merchantId;
|
||||
|
||||
@Value("${alipay.hk.segment-id}")
|
||||
private static String segmentId;
|
||||
@Value("${alipayHK.segmentId}")
|
||||
private String segmentId;
|
||||
|
||||
@Value("${alipay.hk.AESKey}")
|
||||
private static String aesKey;
|
||||
@Value("${alipayHK.AESKey}")
|
||||
private String aesKey;
|
||||
|
||||
@Value("${alipay.hk.rsaPrivateKey}")
|
||||
private static String privateKeyPath;
|
||||
@Value("${alipayHK.rsaPrivateKey}")
|
||||
private String privateKeyPath;
|
||||
|
||||
@Value("${alipayHK.rsaPublicKey}")
|
||||
private String publicKeyPath;
|
||||
|
||||
@Value("${alipay.hk.rsaPublicKey}")
|
||||
private static String publicKeyPath;
|
||||
|
||||
/**
|
||||
* 加密
|
||||
@@ -55,7 +64,7 @@ public class AlipayHKEncryptionUtil {
|
||||
* @throws BadPaddingException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static AlipayHKRequestDTO AESCBCWithRSA(HashMap<String, Object> param, String serviceName) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {
|
||||
public AlipayHKRequestDTO AESCBCWithRSA(HashMap<String, Object> param, String serviceName) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {
|
||||
// Pre-shared secret key, DO NOT hardcode this key
|
||||
String key = aesKey;
|
||||
// The path to the rsa private key file, DO NOT save this key to a publicly accessible location
|
||||
@@ -187,7 +196,7 @@ public class AlipayHKEncryptionUtil {
|
||||
/**
|
||||
* 使用 AES 密钥和随机向量进行解密
|
||||
*/
|
||||
public static String decryptAES(String encryptedText, String iv) throws Exception {
|
||||
public String decryptAES(String encryptedText, String iv) throws Exception {
|
||||
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
|
||||
byte[] ivBytes = Base64.getDecoder().decode(iv);
|
||||
|
||||
@@ -201,7 +210,7 @@ public class AlipayHKEncryptionUtil {
|
||||
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static void test() throws Exception {
|
||||
public void test() throws Exception {
|
||||
// 加密数据
|
||||
AlipayHKParametersDTO requestMessage = new AlipayHKParametersDTO();
|
||||
requestMessage.setService("create_order");
|
||||
@@ -326,4 +335,29 @@ public class AlipayHKEncryptionUtil {
|
||||
random.nextBytes(iv);
|
||||
return iv;
|
||||
}
|
||||
|
||||
public Boolean signatureVerification(String data, String signatureBase64){
|
||||
|
||||
Base64.Decoder decoder = Base64.getDecoder();
|
||||
// Verify key
|
||||
try {
|
||||
// PublicKey publicKey = readPublicKey(new File(publicKeyPath));
|
||||
InputStreamReader isrPub = new InputStreamReader(new FileInputStream(publicKeyPath));
|
||||
PEMParser pemParserPub = new PEMParser(isrPub);
|
||||
SubjectPublicKeyInfo pubInfo = (SubjectPublicKeyInfo) pemParserPub.readObject();
|
||||
AsymmetricKeyParameter pubKey = PublicKeyFactory.createKey(pubInfo);
|
||||
// Verifying
|
||||
RSADigestSigner verifier = new RSADigestSigner(new SHA256Digest());
|
||||
verifier.init(false, pubKey);
|
||||
byte[] signMessageForVerifing = data.getBytes();
|
||||
byte[] signatureBase64ForVerifing = decoder.decode(signatureBase64);
|
||||
verifier.update(signMessageForVerifing, 0, signMessageForVerifing.length);
|
||||
Boolean verifyResult = verifier.verifySignature(signatureBase64ForVerifing);
|
||||
return verifyResult;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AlipayHKRequestUtil {
|
||||
|
||||
public static String createOrder(AlipayHKRequestDTO alipayHKRequestDTO) throws IOException {
|
||||
public String createOrder(AlipayHKRequestDTO alipayHKRequestDTO) throws IOException {
|
||||
OkHttpClient client = new OkHttpClient().newBuilder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
|
||||
@@ -32,22 +34,28 @@ public class AlipayHKRequestUtil {
|
||||
RequestBody body = RequestBody.create(mediaType, jsonString);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
// .url("https://aqs-api.sandbox-codpayment.com")
|
||||
.url("https://aqs-api.sandbox-codpayment.com/v1/service")
|
||||
.method("POST", body)
|
||||
.addHeader("Content-Type", "application/json;charset=utf-8")
|
||||
.build();
|
||||
Response response = null;
|
||||
Response response;
|
||||
String bodyString;
|
||||
try {
|
||||
// log.info("generateSketchOrPrint请求入参content###{}", JSON.toJSONString(alipayHKRequestDTO, SerializerFeature.WriteMapNullValue));
|
||||
response = client.newCall(request).execute();
|
||||
assert response.body() != null;
|
||||
bodyString = response.body().string();
|
||||
} catch (Exception e) {
|
||||
// log.error("PythonService##generateSketchOrPrint异常###{}", ExceptionUtil.getThrowableList(ioException));
|
||||
// throw new BusinessException("generate.interface.error");
|
||||
throw new BusinessException(e.getMessage());
|
||||
}
|
||||
return response.body().string();
|
||||
JSONObject jsonObject = JSONObject.parseObject(bodyString);
|
||||
boolean success = (boolean) jsonObject.get("success");
|
||||
if (success){
|
||||
return bodyString;
|
||||
} else {
|
||||
String message = jsonObject.get("error_code").toString() + ":" + jsonObject.get("error");
|
||||
log.error("Alipay return message : {}", message);
|
||||
throw new BusinessException("Alipay return message : " + message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,40 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.service.AlipayHKService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/api/ali-pay-hk")
|
||||
@RequestMapping("/api/alipay-hk")
|
||||
@Api(tags = "网站支付 香港支付宝")
|
||||
@Slf4j
|
||||
public class AlipayHKController {
|
||||
|
||||
public Response<String> createOrder(){
|
||||
return Response.success();
|
||||
@Resource
|
||||
private AlipayHKService alipayHKService;
|
||||
|
||||
@ApiOperation(value = "创建订单")
|
||||
@PostMapping(value = "/createOrder")
|
||||
public Response<String> createOrder(@RequestParam Integer amount, @RequestParam String wallet) {
|
||||
String order = alipayHKService.createOrder(amount, wallet);
|
||||
return Response.success(order);
|
||||
}
|
||||
|
||||
@ApiOperation("支付通知")
|
||||
@PostMapping("/trade/notify")
|
||||
public String callback(@RequestParam Map<String, String> params){
|
||||
return alipayHKService.callback(params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class PaymentInfo extends BaseEntity{
|
||||
|
||||
private String tradeState;//交易状态
|
||||
|
||||
private Integer payerTotal;//支付金额(分)
|
||||
private Long payerTotal;//支付金额(元)
|
||||
|
||||
private String content;//通知参数
|
||||
}
|
||||
|
||||
30
src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java
Normal file
30
src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AlipayHKCallbackDTO {
|
||||
|
||||
private String transaction_id;
|
||||
|
||||
private Long amount;
|
||||
|
||||
private String currency;
|
||||
|
||||
private String payment_time;
|
||||
|
||||
private String merchant_id;
|
||||
|
||||
private String segment_id;
|
||||
|
||||
private String out_trade_no;
|
||||
|
||||
private String type;
|
||||
|
||||
private String status;
|
||||
|
||||
private String pid;
|
||||
|
||||
private String subject;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.model.dto.AlipayHKCallbackDTO;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface AlipayHKService {
|
||||
|
||||
String createOrder(Integer amount, String wallet);
|
||||
|
||||
String callback(Map<String, String> params);
|
||||
|
||||
void processOrder(AlipayHKCallbackDTO alipayHKCallbackDTO);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.model.dto.AlipayHKCallbackDTO;
|
||||
import com.paypal.orders.Order;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -11,4 +12,6 @@ public interface PaymentInfoService {
|
||||
void createPaymentInfoForAliPay(Map<String, String> params);
|
||||
|
||||
void createPaymentInfoForPayPal(Order order);
|
||||
|
||||
void createPaymentInfoForAliPayHK(AlipayHKCallbackDTO alipayHKCallbackDTO);
|
||||
}
|
||||
|
||||
@@ -1,50 +1,113 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.constant.AlipayHKConstant;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
import com.ai.da.service.AlipayHKService;
|
||||
import com.ai.da.common.enums.OrderStatusEnum;
|
||||
import com.ai.da.common.enums.PayTypeEnum;
|
||||
import com.ai.da.common.utils.AlipayHKEncryptionUtil;
|
||||
import com.ai.da.common.utils.AlipayHKRequestUtil;
|
||||
import com.ai.da.mapper.primary.entity.OrderInfo;
|
||||
import com.ai.da.model.dto.AlipayHKCallbackDTO;
|
||||
import com.ai.da.model.dto.AlipayHKRequestDTO;
|
||||
import com.ai.da.service.*;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AlipayHKServiceImpl implements AlipayHKService {
|
||||
|
||||
@Value("${alipay.hk.merchant-id}")
|
||||
private static String merchantId;
|
||||
@Value("${alipayHK.merchantId}")
|
||||
private String merchantId;
|
||||
|
||||
@Value("${alipay.hk.segment-id}")
|
||||
private static String segmentId;
|
||||
@Value("${alipayHK.segmentId}")
|
||||
private String segmentId;
|
||||
|
||||
@Value("${alipay.hk.AESKey}")
|
||||
private static String aesKey;
|
||||
@Value("${alipayHK.AESKey}")
|
||||
private String aesKey;
|
||||
|
||||
@Value("${alipay.hk.rsaPrivateKey}")
|
||||
private static String privateKeyPath;
|
||||
@Value("${alipayHK.rsaPrivateKey}")
|
||||
private String privateKeyPath;
|
||||
|
||||
@Value("${alipay.hk.rsaPublicKey}")
|
||||
private static String publicKeyPath;
|
||||
@Value("${alipayHK.rsaPublicKey}")
|
||||
private String publicKeyPath;
|
||||
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
@Resource
|
||||
private PaymentInfoService paymentInfoService;
|
||||
@Resource
|
||||
private CreditsService creditsService;
|
||||
@Resource
|
||||
private AlipayHKEncryptionUtil alipayHKEncryptionUtil;
|
||||
@Resource
|
||||
private AlipayHKRequestUtil alipayHKRequestUtil;
|
||||
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
public void createOrder(Integer amount){
|
||||
@Override
|
||||
public String createOrder(Integer amount, String wallet){
|
||||
|
||||
HashMap<String, Object> param = new HashMap<>();
|
||||
String orderRef = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
param.put("order_ref", orderRef);
|
||||
param.put("amount", Integer.parseInt(CreditsEventsEnum.PRICE.getValue()) * amount);
|
||||
param.put("subject", "AiDA Credits Purchase");
|
||||
param.put("wallet", "ALIPAYHK");
|
||||
param.put("segment_id", segmentId);
|
||||
param.put("payment_solution", "WAP");
|
||||
try{
|
||||
HashMap<String, Object> param = new HashMap<>();
|
||||
String orderRef = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
param.put("order_ref", orderRef);
|
||||
param.put("amount", Integer.parseInt(CreditsEventsEnum.PRICE.getValue()) * amount);
|
||||
param.put("subject", "AiDA Credits Purchase");
|
||||
// ALIPAYHK 或者 ALIPAYCN
|
||||
param.put("wallet", wallet);
|
||||
param.put("segment_id", segmentId);
|
||||
param.put("payment_solution", "WAP");
|
||||
log.info("alipay-hk 创建订单,参数信息: {}", param);
|
||||
// 生成订单
|
||||
log.info("创建订单");
|
||||
OrderInfo orderInfo = orderInfoService.createOrderByProductId(amount, PayTypeEnum.ALIPAY_HK.getType());
|
||||
// 加密
|
||||
AlipayHKRequestDTO alipayHKRequestDTO = alipayHKEncryptionUtil.AESCBCWithRSA(param, AlipayHKConstant.CREATE_ORDER);
|
||||
// 请求Alipay服务端
|
||||
String response = alipayHKRequestUtil.createOrder(alipayHKRequestDTO);
|
||||
// 获取response中的加密数据
|
||||
JSONObject responseObj = JSONObject.parseObject(response);
|
||||
JSONObject resultObj = JSONObject.parseObject(responseObj.get("result").toString());
|
||||
String nonce = resultObj.get("nonce").toString();
|
||||
String message = resultObj.get("message").toString();
|
||||
// 解密
|
||||
String s = alipayHKEncryptionUtil.decryptAES(message, nonce);
|
||||
JSONObject jsonObject = JSONObject.parseObject(s);
|
||||
|
||||
String orderId = jsonObject.get("out_trade_no").toString();
|
||||
|
||||
orderInfoService.updateOrderNoById(orderInfo.getId(), orderId);
|
||||
|
||||
|
||||
log.info("create_order 接口返回信息 :{}", s);
|
||||
|
||||
return s;
|
||||
|
||||
|
||||
}catch (Exception e){
|
||||
log.error("订单创建失败 : {}", e.getMessage());
|
||||
// todo 或者抛异常
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,8 +116,122 @@ public class AlipayHKServiceImpl implements AlipayHKService {
|
||||
* 异步回调
|
||||
* @return
|
||||
*/
|
||||
public void callback(){
|
||||
public String callback(Map<String, String> params){
|
||||
log.info("支付通知正在执行");
|
||||
log.info("通知参数 ===> {}", params);
|
||||
|
||||
String result = "failure";
|
||||
|
||||
String data = params.get("data");
|
||||
String signature = params.get("signature");
|
||||
|
||||
try {
|
||||
// 异步回调验签
|
||||
Boolean verification = alipayHKEncryptionUtil.signatureVerification(data, signature);
|
||||
|
||||
if (!verification){
|
||||
log.error("alipay-hk 验签失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
AlipayHKCallbackDTO alipayHKCallbackDTO = JSONObject.parseObject(data, AlipayHKCallbackDTO.class);
|
||||
//按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,
|
||||
//1 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
|
||||
String outTradeNo = alipayHKCallbackDTO.getOut_trade_no();
|
||||
OrderInfo order = orderInfoService.getOrderByOrderNo(outTradeNo);
|
||||
if(order == null){
|
||||
log.error("订单不存在");
|
||||
return result;
|
||||
}
|
||||
|
||||
//2 判断 total_amount 是否确实为该订单的实际金额(即商户订单创建时的金额)
|
||||
Long totalAmount = alipayHKCallbackDTO.getAmount();
|
||||
Long totalFee = order.getTotalFee().longValue();
|
||||
if(totalAmount != totalFee){
|
||||
log.error("金额校验失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
//3 校验通知中的 seller_id(或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方
|
||||
String sellerId = alipayHKCallbackDTO.getMerchant_id();
|
||||
String sellerIdProperty = merchantId;
|
||||
if(!sellerId.equals(sellerIdProperty)){
|
||||
log.error("商家pid校验失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
//4 验证 app_id 是否为该商户本身
|
||||
String segId = alipayHKCallbackDTO.getSegment_id();
|
||||
String segmentIdProperty = segmentId;
|
||||
if(!segId.equals(segmentIdProperty)){
|
||||
log.error("segmentId校验失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
//在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS时,
|
||||
// 支付宝才会认定为买家付款成功。
|
||||
String tradeStatus = alipayHKCallbackDTO.getStatus();
|
||||
if(!AlipayHKConstant.STATUS_PAID.equals(tradeStatus)){
|
||||
log.error("支付未成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
processOrder(alipayHKCallbackDTO);
|
||||
result = "success";
|
||||
}catch (Exception e){
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void processOrder(AlipayHKCallbackDTO alipayHKCallbackDTO) {
|
||||
|
||||
log.info("处理订单");
|
||||
|
||||
//获取订单号
|
||||
String orderNo = alipayHKCallbackDTO.getOut_trade_no();
|
||||
String totalAmount = alipayHKCallbackDTO.getAmount().toString();
|
||||
|
||||
/*在对业务数据进行状态检查和处理之前,
|
||||
要采用数据锁进行并发控制,
|
||||
以避免函数重入造成的数据混乱*/
|
||||
//尝试获取锁:
|
||||
// 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放
|
||||
if(lock.tryLock()) {
|
||||
try {
|
||||
//处理重复通知
|
||||
//接口调用的幂等性:无论接口被调用多少次,以下业务执行一次
|
||||
// String orderStatus = orderInfoService.getOrderStatus(orderNo);
|
||||
OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo);
|
||||
String orderStatus = orderByOrderNo.getOrderStatus();
|
||||
// 当订单状态处于未支付或超时已关闭时,更新订单状态
|
||||
if (!OrderStatusEnum.NOT_PAY.getType().equals(orderStatus) || !OrderStatusEnum.TIMEOUT_CLOSED.getType().equals(orderStatus)) {
|
||||
return;
|
||||
}
|
||||
//更新订单状态
|
||||
orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS);
|
||||
//记录支付日志
|
||||
paymentInfoService.createPaymentInfoForAliPayHK(alipayHKCallbackDTO);
|
||||
// 添加积分变更记录
|
||||
creditsService.insertToCreditsDetail(orderByOrderNo.getAccountId(),
|
||||
CreditsEventsEnum.BUY_CREDITS.getName() + "--AlipayHK",
|
||||
CreditsEventsEnum.BUY_CREDITS.getValue(),
|
||||
"positive");
|
||||
// 更新积分
|
||||
creditsService.buyCredits(orderByOrderNo.getAccountId(),Integer.parseInt(totalAmount) / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
} finally {
|
||||
//要主动释放锁
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,10 +265,28 @@ public class AlipayHKServiceImpl implements AlipayHKService {
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// test();
|
||||
// AESCBCWithRSA();
|
||||
// decrypt();
|
||||
// public static void main(String[] args) throws Exception {
|
||||
//// test();
|
||||
//// AESCBCWithRSA();
|
||||
//// decrypt();
|
||||
// }
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Supported TLS versions:");
|
||||
String[] tlsVersions = getSupportedTLSVersions();
|
||||
Arrays.stream(tlsVersions).forEach(System.out::println);
|
||||
}
|
||||
|
||||
public static String[] getSupportedTLSVersions() {
|
||||
try {
|
||||
SSLContext context = SSLContext.getDefault();
|
||||
SSLSocketFactory factory = context.getSocketFactory();
|
||||
String[] supportedProtocols = factory.getDefaultCipherSuites();
|
||||
return supportedProtocols;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ai.da.service.impl;
|
||||
import com.ai.da.common.enums.PayTypeEnum;
|
||||
import com.ai.da.mapper.primary.PaymentInfoMapper;
|
||||
import com.ai.da.mapper.primary.entity.PaymentInfo;
|
||||
import com.ai.da.model.dto.AlipayHKCallbackDTO;
|
||||
import com.ai.da.service.PaymentInfoService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.gson.Gson;
|
||||
@@ -48,7 +49,8 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
|
||||
paymentInfo.setTransactionId(transactionId);
|
||||
paymentInfo.setTradeType(tradeType);
|
||||
paymentInfo.setTradeState(tradeState);
|
||||
paymentInfo.setPayerTotal(payerTotal);
|
||||
// 原来的单位是:分 Int 现改为:元 Long
|
||||
paymentInfo.setPayerTotal(payerTotal / 100L);
|
||||
paymentInfo.setContent(plainText);
|
||||
|
||||
baseMapper.insert(paymentInfo);
|
||||
@@ -80,7 +82,8 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
|
||||
paymentInfo.setTransactionId(transactionId);
|
||||
paymentInfo.setTradeType("电脑网站支付");
|
||||
paymentInfo.setTradeState(tradeStatus);
|
||||
paymentInfo.setPayerTotal(totalAmountInt);
|
||||
// 原来的单位是分 Int 现改为元 Long
|
||||
paymentInfo.setPayerTotal(totalAmountInt / 100L);
|
||||
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(params, HashMap.class);
|
||||
@@ -95,7 +98,7 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
|
||||
log.info("记录支付日志");
|
||||
|
||||
// int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
|
||||
int totalAmountInt = new BigDecimal(order.purchaseUnits().get(0).payments().captures().get(0).amount().value()).intValue();
|
||||
Long totalAmountInt = new BigDecimal(order.purchaseUnits().get(0).payments().captures().get(0).amount().value()).longValue();
|
||||
|
||||
PaymentInfo paymentInfo = new PaymentInfo();
|
||||
paymentInfo.setOrderNo(order.id());
|
||||
@@ -103,6 +106,7 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
|
||||
paymentInfo.setTransactionId(order.id());
|
||||
paymentInfo.setTradeType("电脑网站支付");
|
||||
paymentInfo.setTradeState(order.status());
|
||||
// todo 确认这里的数据单位是不是元
|
||||
paymentInfo.setPayerTotal(totalAmountInt);
|
||||
|
||||
Gson gson = new Gson();
|
||||
@@ -111,4 +115,35 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
|
||||
|
||||
baseMapper.insert(paymentInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPaymentInfoForAliPayHK(AlipayHKCallbackDTO alipayHKCallbackDTO) {
|
||||
|
||||
log.info("记录支付日志");
|
||||
|
||||
//获取订单号
|
||||
String orderNo = alipayHKCallbackDTO.getOut_trade_no();
|
||||
//业务编号
|
||||
String transactionId = alipayHKCallbackDTO.getTransaction_id();
|
||||
//交易状态
|
||||
String tradeStatus = alipayHKCallbackDTO.getStatus();
|
||||
//交易金额
|
||||
String totalAmount = alipayHKCallbackDTO.getAmount().toString();
|
||||
// int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
|
||||
Long totalAmountInt = new BigDecimal(totalAmount).longValue();
|
||||
|
||||
PaymentInfo paymentInfo = new PaymentInfo();
|
||||
paymentInfo.setOrderNo(orderNo);
|
||||
paymentInfo.setPaymentType(PayTypeEnum.ALIPAY_HK.getType());
|
||||
paymentInfo.setTransactionId(transactionId);
|
||||
paymentInfo.setTradeType("电脑网站支付");
|
||||
paymentInfo.setTradeState(tradeStatus);
|
||||
paymentInfo.setPayerTotal(totalAmountInt);
|
||||
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(alipayHKCallbackDTO);
|
||||
paymentInfo.setContent(json);
|
||||
|
||||
baseMapper.insert(paymentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
alipay.hk.merchant-id=3015240422190522
|
||||
|
||||
alipay.hk.segment-id=2971373831
|
||||
|
||||
alipay.hk.AESKey=UzRC2CncDUP6VlEd
|
||||
|
||||
alipay.hk.rsaPrivateKey=files/CODE-CREATE LIMITED-3015240422190522-merchant.private.key.txt
|
||||
|
||||
alipay.hk.rsaPublicKey=files/CODE-CREATE LIMITED.merchant.aqs.public.key.pem
|
||||
|
||||
alipay.hk.api.url=https://aqs-api.sandbox-codpayment.com/
|
||||
@@ -34,6 +34,13 @@ alipay.notify-url=http://18.167.251.121:10090/api/ali-pay/trade/notify
|
||||
#alipay.notify-url=https://3b38-18-167-251-121.ngrok-free.app/api/ali-pay/trade/notify
|
||||
|
||||
|
||||
alipayHK.merchantId=3015240422190522
|
||||
alipayHK.segmentId=2971373831
|
||||
alipayHK.AESKey=UzRC2CncDUP6VlEd
|
||||
alipayHK.rsaPrivateKey=files/CODE-CREATE LIMITED-3015240422190522-merchant.private.key.txt
|
||||
alipayHK.rsaPublicKey=files/CODE-CREATE LIMITED.merchant.aqs.public.key.pem
|
||||
alipayHK.api.url=https://aqs-api.sandbox-codpayment.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ spring.security.jwtExpiration=8640000000
|
||||
#spring security权限设置 认证了token还要认证权限 不然报错Full authentication is required to access this resource
|
||||
spring.security.ignorePaths=/,/favicon.ico,/doc.html,/webjars/**,/swagger-resources,/v2/api-docs,\
|
||||
/api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**,/api/workspace/**,/api/classification/**,\
|
||||
/api/product/**,/api/ali-pay/**,/api/order-info/**,/api/paypal/**,/api/credits/**,/api/inquiry/**,/api/tasks/**,/api/python/prepareForSR
|
||||
/api/product/**,/api/ali-pay/**,/api/order-info/**,/api/paypal/**,/api/credits/**,/api/inquiry/**,/api/tasks/**,/api/python/prepareForSR,/api/alipay-hk/**
|
||||
spring.security.authApi=/auth/login
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user