Merge remote-tracking branch 'origin/test' into test
# Conflicts: # cash-api/order-server/src/main/java/com/czg/controller/NotifyController.java # cash-sdk/aggregation-pay/src/main/java/com/czg/PayManager.java
This commit is contained in:
@@ -3,9 +3,13 @@ package com.czg.controller;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.PolyPayUtils;
|
||||
import com.czg.CzgPayUtils;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.entity.PolyBaseResp;
|
||||
import com.czg.dto.req.WechatNotifyReqDto;
|
||||
import com.czg.dto.req.WechatPayNotifyDataDto;
|
||||
import com.czg.entity.CzgBaseRespParams;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.entity.MkShopConsumeDiscountRecord;
|
||||
import com.czg.market.service.MkDistributionUserService;
|
||||
import com.czg.market.service.MkShopConsumeDiscountRecordService;
|
||||
@@ -15,15 +19,13 @@ import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.order.service.OrderInfoCustomService;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.market.service.impl.AppWxServiceImpl;
|
||||
import com.czg.third.wechat.WechatReqUtils;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -59,10 +61,52 @@ public class NotifyController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* 原生支付回调
|
||||
*/
|
||||
@RequestMapping("/native/pay/{platform}")
|
||||
public String pay(@PathVariable String platform, @RequestBody JSONObject json) {
|
||||
if (PayCst.Platform.WECHAT.equalsIgnoreCase(platform)) {
|
||||
// 微信
|
||||
WechatNotifyReqDto reqDto = JSONObject.parseObject(json.toJSONString(), WechatNotifyReqDto.class);
|
||||
log.info("【微信支付回调】收到微信支付回调 data: {}", JSONObject.toJSONString(reqDto));
|
||||
|
||||
String decrypted = WechatReqUtils.decryptRespParam(null, reqDto);
|
||||
log.info("【微信支付回调】解密数据 {}", decrypted);
|
||||
|
||||
WechatPayNotifyDataDto dataDto = JSONObject.parseObject(decrypted, WechatPayNotifyDataDto.class);
|
||||
return "success";
|
||||
} else if (PayCst.Platform.ALIPAY.equalsIgnoreCase(platform)) {
|
||||
// 支付宝
|
||||
return "success";
|
||||
}
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
|
||||
/**
|
||||
* 原生退款回调
|
||||
*/
|
||||
@RequestMapping("/native/refund/{platform}")
|
||||
public String refund(@PathVariable String platform, @RequestBody JSONObject json) {
|
||||
if (PayCst.Platform.WECHAT.equalsIgnoreCase(platform)) {
|
||||
// 微信
|
||||
WechatNotifyReqDto reqDto = JSONObject.parseObject(json.toJSONString(), WechatNotifyReqDto.class);
|
||||
log.info("【微信退款回调】收到微信退款回调 data: {}", JSONObject.toJSONString(reqDto));
|
||||
String decrypted = WechatReqUtils.decryptRespParam(null, reqDto);
|
||||
log.info("【微信退款回调】解密数据 {}", decrypted);
|
||||
|
||||
return "success";
|
||||
} else if (PayCst.Platform.ALIPAY.equalsIgnoreCase(platform)) {
|
||||
// 支付宝
|
||||
return "success";
|
||||
}
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/payCallBack")
|
||||
public String notifyCallBack(@RequestBody PolyBaseResp respParams) {
|
||||
JSONObject czg = PolyPayUtils.getCzg(respParams);
|
||||
public String notifyCallBack(@RequestBody CzgBaseRespParams respParams) {
|
||||
JSONObject czg = CzgPayUtils.getCzg(respParams);
|
||||
AssertUtil.isNull(czg, "支付回调数据为空");
|
||||
log.info("支付回调数据为:{}", czg);
|
||||
orderInfoCustomService.payCallBackOrder(czg.getString("mchOrderNo"), czg, 0);
|
||||
@@ -89,10 +133,10 @@ public class NotifyController {
|
||||
|
||||
@RequestMapping("/native/wx/pay/distributionRecharge")
|
||||
public String nativeNotify(HttpServletRequest request) throws IOException {
|
||||
// String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
// String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
// String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
// String signature = request.getHeader("Wechatpay-Signature");
|
||||
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
String signature = request.getHeader("Wechatpay-Signature");
|
||||
String result = IoUtil.readUtf8(request.getInputStream());
|
||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||
JSONObject resource = jsonObject.getJSONObject("resource");
|
||||
@@ -127,8 +171,8 @@ public class NotifyController {
|
||||
|
||||
|
||||
@RequestMapping("/refundCallBack")
|
||||
public String refundCallBack(@RequestBody PolyBaseResp respParams) {
|
||||
JSONObject czg = PolyPayUtils.getCzg(respParams);
|
||||
public String refundCallBack(@RequestBody CzgBaseRespParams respParams) {
|
||||
JSONObject czg = CzgPayUtils.getCzg(respParams);
|
||||
AssertUtil.isNull(czg, "退款回调数据为空");
|
||||
log.info("退款回调数据为:{}", czg);
|
||||
orderInfoCustomService.refundCallBackOrder(czg.getString("mchOrderNo"), czg);
|
||||
|
||||
@@ -1,22 +1,78 @@
|
||||
package com.czg;
|
||||
|
||||
import com.czg.dto.req.PayParamsDto;
|
||||
import com.czg.dto.req.RefundParamsDto;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.AlipayIsvPayManager;
|
||||
import com.czg.third.wechat.WechatPayManager;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/9 11:24
|
||||
*/
|
||||
public class PayManager {
|
||||
|
||||
public static void jsapiPay(PayParamsDto paramsDto) {
|
||||
/**
|
||||
* jsapi支付
|
||||
*
|
||||
* @param paramsDto 参数
|
||||
* @return 结果
|
||||
*/
|
||||
public static Map<String, Object> jsapiPay(PayParamsDto paramsDto) {
|
||||
paramsDto.verifyParams();
|
||||
|
||||
if (PayCst.Platform.WECHAT.equals(paramsDto.getPlatform())) {
|
||||
WechatPayManager.jsapiPay(null, paramsDto);
|
||||
return WechatPayManager.jsapiPay(null, paramsDto);
|
||||
} else if (PayCst.Platform.ALIPAY.equals(paramsDto.getPlatform())) {
|
||||
AlipayIsvPayManager.jsapiPay(null, paramsDto);
|
||||
return AlipayIsvPayManager.jsapiPay(null, paramsDto);
|
||||
} else {
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 条码支付
|
||||
*
|
||||
* @param paramsDto 参数
|
||||
* @return 结果
|
||||
*/
|
||||
public static Map<String, Object> barPay(PayParamsDto paramsDto) {
|
||||
paramsDto.verifyParams();
|
||||
|
||||
if (PayCst.Platform.WECHAT.equals(paramsDto.getPlatform())) {
|
||||
return WechatPayManager.barPay(null, paramsDto);
|
||||
} else if (PayCst.Platform.ALIPAY.equals(paramsDto.getPlatform())) {
|
||||
return AlipayIsvPayManager.barPay(null, paramsDto);
|
||||
} else {
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单状态
|
||||
*/
|
||||
public static Map<String, Object> queryOrderStatus(String platform, String orderNo, String subMerchantId) {
|
||||
if (PayCst.Platform.WECHAT.equals(platform)) {
|
||||
return WechatPayManager.queryOrder(null, orderNo, subMerchantId);
|
||||
} else if (PayCst.Platform.ALIPAY.equals(platform)) {
|
||||
return AlipayIsvPayManager.queryOrder(null, orderNo, subMerchantId);
|
||||
} else {
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
public static Map<String, Object> refund(String platform, RefundParamsDto paramsDto) {
|
||||
if (PayCst.Platform.WECHAT.equals(platform)) {
|
||||
return WechatPayManager.refundOrder(null, paramsDto);
|
||||
} else if (PayCst.Platform.ALIPAY.equals(platform)) {
|
||||
return AlipayIsvPayManager.refundOrder(null, paramsDto);
|
||||
} else {
|
||||
throw new CzgException("不支持的支付平台");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +91,10 @@ public class PayManager {
|
||||
jsapiPay(new PayParamsDto()
|
||||
.setPlatform(PayCst.Platform.WECHAT)
|
||||
.setAppId("wxd88fffa983758a30")
|
||||
.setOpenId("123123123")
|
||||
.setOpenId("or1l86yipGvwyfPhrKIAcQuSfAV8")
|
||||
.setOrderNo("1111231231213")
|
||||
.setTitle("1213")
|
||||
.setMerchantId("1665469114")
|
||||
.setMerchantId("1738216504")
|
||||
.setBody("1213")
|
||||
.setAmount(1000L)
|
||||
.setPayParams("{\"app_auth_token\": \"ssss\"}")
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款参数
|
||||
* @author yjjie
|
||||
* @date 2026/1/14 11:37
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RefundParamsDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 平台
|
||||
* {@link com.czg.PayCst.Platform}
|
||||
*/
|
||||
private String platform;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 退款单号
|
||||
*/
|
||||
private String refundOrderNo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 退款金额
|
||||
*/
|
||||
private Long refundAmount;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 订单原金额
|
||||
*/
|
||||
private Long orderAmount;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 退款原因
|
||||
*/
|
||||
private String refundReason;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 退款回调地址
|
||||
*/
|
||||
private String refundNotifyUrl;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 微信商户号
|
||||
*/
|
||||
private String merchantId;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 支付宝授权信息
|
||||
*/
|
||||
private String alipayAuthInfo;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/23 21:47
|
||||
*/
|
||||
@Data
|
||||
public class WechatNotifyReqDto {
|
||||
|
||||
private String id;
|
||||
@JSONField(name = "create_time")
|
||||
private String createTime;
|
||||
@JSONField(name = "resource_type")
|
||||
private String resourceType;
|
||||
@JSONField(name = "event_type")
|
||||
private String eventType;
|
||||
private String summary;
|
||||
private Resource resource;
|
||||
|
||||
@Data
|
||||
public static class Resource {
|
||||
@JSONField(name = "resource_type")
|
||||
private String originalType;
|
||||
private String algorithm;
|
||||
private String ciphertext;
|
||||
@JSONField(name = "associated_data")
|
||||
private String associatedData;
|
||||
private String nonce;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/23 22:21
|
||||
*/
|
||||
@Data
|
||||
public class WechatPayNotifyDataDto {
|
||||
|
||||
/**
|
||||
* 公众账号ID
|
||||
*/
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
private String mchid;
|
||||
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
@JSONField(name = "out_trade_no")
|
||||
private String outTradeNo;
|
||||
|
||||
/**
|
||||
* 微信支付订单号
|
||||
*/
|
||||
@JSONField(name = "transaction_id")
|
||||
private String transactionId;
|
||||
|
||||
/**
|
||||
* 交易类型
|
||||
* JSAPI:公众号支付、小程序支付
|
||||
* NATIVE:Native支付
|
||||
* APP:APP支付
|
||||
* MICROPAY:付款码支付
|
||||
* MWEB:H5支付
|
||||
* FACEPAY:刷脸支付
|
||||
*/
|
||||
@JSONField(name = "trade_type")
|
||||
private String tradeType;
|
||||
|
||||
/**
|
||||
* 交易状态
|
||||
* SUCCESS—支付成功
|
||||
* REFUND—转入退款
|
||||
* NOTPAY—未支付
|
||||
* CLOSED—已关闭
|
||||
* REVOKED—已撤销(刷卡支付)
|
||||
* USERPAYING--用户支付中
|
||||
* PAYERROR--支付失败(其他原因,如银行返回失败)
|
||||
*/
|
||||
@JSONField(name = "trade_state")
|
||||
private String tradeState;
|
||||
|
||||
/**
|
||||
* 交易状态描述
|
||||
*/
|
||||
@JSONField(name = "trade_state_desc")
|
||||
private String tradeStateDesc;
|
||||
|
||||
/**
|
||||
* 付款银行
|
||||
*/
|
||||
@JSONField(name = "bank_type")
|
||||
private String bankType;
|
||||
|
||||
/**
|
||||
* 商户数据包
|
||||
*/
|
||||
private String attach;
|
||||
|
||||
/**
|
||||
* 支付完成时间
|
||||
*/
|
||||
@JSONField(name = "success_time")
|
||||
private String successTime;
|
||||
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private Amount amount;
|
||||
|
||||
@Data
|
||||
public static class Amount {
|
||||
/**
|
||||
* 用户支付金额
|
||||
*/
|
||||
@JSONField(name = "payer_total")
|
||||
private Integer payerTotal;
|
||||
|
||||
/**
|
||||
* 货币类型
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private Integer total;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return "SUCCESS".equals(tradeState);
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return "CLOSED".equals(tradeState);
|
||||
}
|
||||
|
||||
public Long getPayAmount() {
|
||||
return Long.valueOf(amount.getTotal());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.alipay.v3.model.ExtendParams;
|
||||
import com.alipay.v3.util.model.CustomizedParams;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.dto.req.PayParamsDto;
|
||||
import com.czg.dto.req.RefundParamsDto;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -26,6 +27,7 @@ public class AlipayIsvPayManager {
|
||||
|
||||
/**
|
||||
* H5支付
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param paramsDto 参数
|
||||
*/
|
||||
@@ -41,7 +43,7 @@ public class AlipayIsvPayManager {
|
||||
model.setTotalAmount(getYuanAmountByFen(paramsDto.getAmount()));
|
||||
model.setSubject(paramsDto.getTitle());
|
||||
model.setBody(paramsDto.getBody());
|
||||
model.setNotifyUrl(paramsDto.getNotifyUrl());
|
||||
model.setNotifyUrl(paramsDto.getNotifyUrl() + "/" + PayCst.Platform.ALIPAY);
|
||||
|
||||
model.setExtendParams(new ExtendParams());
|
||||
CustomizedParams customizedParams = new CustomizedParams();
|
||||
@@ -63,6 +65,7 @@ public class AlipayIsvPayManager {
|
||||
|
||||
/**
|
||||
* 条码支付
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param paramsDto 参数
|
||||
*/
|
||||
@@ -82,6 +85,14 @@ public class AlipayIsvPayManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Object> queryOrder(AlipayConfigDto configDto, String orderNo, String subMerchantId) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public static Map<String, Object> refundOrder(AlipayConfigDto configDto, RefundParamsDto paramsDto) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额转换
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import javax.crypto.AEADBadTagException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 微信参数 AES 解密
|
||||
* @author GYJoker
|
||||
*/
|
||||
public class WechatAesUtil {
|
||||
static final int KEY_LENGTH_BYTE = 32;
|
||||
static final int TAG_LENGTH_BIT = 128;
|
||||
private final byte[] aesKey;
|
||||
public WechatAesUtil(byte[] key) {
|
||||
if (key.length != KEY_LENGTH_BYTE) {
|
||||
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
|
||||
}
|
||||
this.aesKey = key;
|
||||
}
|
||||
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
|
||||
throws GeneralSecurityException {
|
||||
try {
|
||||
|
||||
// 调试信息:打印参数信息
|
||||
System.out.println("associatedData长度: " + (associatedData != null ? associatedData.length : 0));
|
||||
System.out.println("nonce长度: " + (nonce != null ? nonce.length : 0));
|
||||
System.out.println("ciphertext长度: " + ciphertext.length());
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
|
||||
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
||||
|
||||
// 处理 associatedData,确保使用空数组而非 null
|
||||
cipher.updateAAD(associatedData != null ? associatedData : new byte[0]);
|
||||
|
||||
byte[] decodedCiphertext = Base64.getDecoder().decode(ciphertext);
|
||||
System.out.println("解码后密文长度: " + decodedCiphertext.length);
|
||||
|
||||
byte[] plaintext = cipher.doFinal(decodedCiphertext);
|
||||
return new String(plaintext, StandardCharsets.UTF_8);
|
||||
} catch (AEADBadTagException e) {
|
||||
// 捕获标签不匹配异常,提供更详细的错误信息
|
||||
throw new GeneralSecurityException("解密失败: 标签不匹配,可能是密钥错误、数据被篡改或参数不匹配", e);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||
throw new IllegalArgumentException("无效的密钥或参数", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.dto.req.PayParamsDto;
|
||||
import com.czg.dto.req.RefundParamsDto;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
@@ -55,7 +57,7 @@ public class WechatPayManager {
|
||||
reqData.put("sub_mchid", paramsDto.getMerchantId());
|
||||
reqData.put("description", paramsDto.getTitle());
|
||||
reqData.put("out_trade_no", paramsDto.getOrderNo());
|
||||
reqData.put("notify_url", paramsDto.getNotifyUrl());
|
||||
reqData.put("notify_url", paramsDto.getNotifyUrl() + "/" + PayCst.Platform.WECHAT);
|
||||
reqData.put("attach", paramsDto.getExtData());
|
||||
|
||||
JSONObject amount = new JSONObject();
|
||||
@@ -99,6 +101,7 @@ public class WechatPayManager {
|
||||
/**
|
||||
* 条码支付
|
||||
* 用户付款码规则:18位纯数字,前缀以10、11、12、13、14、15开头
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param paramsDto 参数
|
||||
*/
|
||||
@@ -195,8 +198,129 @@ public class WechatPayManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param orderNo 订单号
|
||||
* @param subMerchantId 子商户号
|
||||
* SUCCESS:支付成功
|
||||
* REFUND:转入退款
|
||||
* NOTPAY:未支付
|
||||
* CLOSED:已关闭
|
||||
* REVOKED:已撤销(仅付款码支付会返回)
|
||||
* USERPAYING:用户支付中(仅付款码支付会返回)
|
||||
* PAYERROR:支付失败(仅付款码支付会返回)
|
||||
*/
|
||||
public static Map<String, Object> queryOrder(WechatPayConfigDto configDto, String orderNo, String subMerchantId) {
|
||||
try {
|
||||
if (configDto == null) {
|
||||
configDto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/pay/partner/transactions/out-trade-no/" + orderNo,
|
||||
Map.of("sp_mchid", configDto.getMerchantId(), "sub_mchid", subMerchantId));
|
||||
log.info("微信查询订单,订单号:{}, 响应:{}", orderNo, resp);
|
||||
|
||||
JSONObject res = new JSONObject();
|
||||
res.put("orderNo", orderNo);
|
||||
|
||||
JSONObject object = JSONObject.parseObject(resp);
|
||||
String tradeState = object.getString("trade_state");
|
||||
res.put("message", object.getString("trade_state_desc"));
|
||||
if (PAY_SUCCESS.equals(tradeState)) {
|
||||
res.put("status", "TRADE_SUCCESS");
|
||||
return res;
|
||||
}
|
||||
|
||||
if ("USERPAYING".equals(tradeState)) {
|
||||
res.put("status", "TRADE_AWAIT");
|
||||
return res;
|
||||
}
|
||||
|
||||
res.put("status", "TRADE_FAIL");
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
log.error("微信查询订单异常: orderNo = {}, e = {}", orderNo, e.getMessage());
|
||||
throw new CzgException("微信查询订单异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param paramsDto 参数
|
||||
* SUCCESS: 退款成功
|
||||
* CLOSED: 退款关闭
|
||||
* PROCESSING: 退款处理中
|
||||
* ABNORMAL: 退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往服务商平台-交易中心,手动处理此笔退款
|
||||
*/
|
||||
public static Map<String, Object> refundOrder(WechatPayConfigDto configDto, RefundParamsDto paramsDto) {
|
||||
try {
|
||||
if (configDto == null) {
|
||||
configDto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
|
||||
JSONObject refundParam = new JSONObject();
|
||||
refundParam.put("sub_mchid", paramsDto.getMerchantId());
|
||||
refundParam.put("out_trade_no", paramsDto.getOrderNo());
|
||||
refundParam.put("out_refund_no", paramsDto.getRefundOrderNo());
|
||||
refundParam.put("reason", paramsDto.getRefundReason());
|
||||
refundParam.put("notify_url", paramsDto.getRefundNotifyUrl() + "/" + PayCst.Platform.WECHAT);
|
||||
|
||||
JSONObject amount = new JSONObject();
|
||||
amount.put("total", paramsDto.getOrderAmount());
|
||||
amount.put("refund", paramsDto.getRefundAmount());
|
||||
amount.put("currency", "CNY");
|
||||
refundParam.put("amount", amount);
|
||||
|
||||
String resp = WechatReqUtils.postReq(configDto, "/v3/refund/domestic/refunds", refundParam.toJSONString());
|
||||
log.info("微信退款,订单号:{}, 响应:{}", paramsDto.getOrderNo(), resp);
|
||||
|
||||
JSONObject object = JSONObject.parseObject(resp);
|
||||
|
||||
JSONObject res = new JSONObject();
|
||||
res.put("mchRefundNo", object.getString("out_refund_no"));
|
||||
res.put("refundOrderId", object.getString("refund_id"));
|
||||
res.put("oriPayOrderId", object.getString("out_trade_no"));
|
||||
res.put("mercNo", paramsDto.getMerchantId());
|
||||
res.put("refundReason", paramsDto.getRefundReason());
|
||||
res.put("payType", PayCst.Platform.WECHAT);
|
||||
res.put("refundTime", object.getString("success_time"));
|
||||
switch (object.getString("status")) {
|
||||
case "SUCCESS":
|
||||
res.put("status", "SUCCESS");
|
||||
break;
|
||||
case "CLOSED":
|
||||
res.put("status", "CLOSED");
|
||||
break;
|
||||
case "PROCESSING":
|
||||
res.put("status", "ING");
|
||||
break;
|
||||
case "ABNORMAL":
|
||||
res.put("status", "INIT");
|
||||
break;
|
||||
default:
|
||||
res.put("status", "FAIL");
|
||||
break;
|
||||
}
|
||||
JSONObject resAmount = object.getJSONObject("amount");
|
||||
if (resAmount != null) {
|
||||
res.put("refundAmt", resAmount.getLong("refund"));
|
||||
res.put("oriAmount", resAmount.getLong("total"));
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
log.error("微信退款异常: orderNo = {}, e = {}", paramsDto.getOrderNo(), e.getMessage());
|
||||
throw new CzgException("微信退款异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将String转换为InputStream
|
||||
*
|
||||
* @param str 待转换的字符串
|
||||
* @return 转换后的InputStream
|
||||
*/
|
||||
@@ -231,14 +355,26 @@ public class WechatPayManager {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
barPay(null, new PayParamsDto()
|
||||
// barPay(null, new PayParamsDto()
|
||||
// .setMerchantId("1738216504")
|
||||
// .setOrderNo("sa101293120sss1")
|
||||
// .setTitle("1213")
|
||||
// .setBody("1213")
|
||||
// .setAmount(1L)
|
||||
// .setAppId("wxd88fffa983758a30")
|
||||
// .setClientIp("127.0.0.1")
|
||||
// .setBarCode("130013153082460022"));
|
||||
|
||||
// Map<String, Object> sss1 = queryOrder(null, "sa101293120sss1", "1738216504");
|
||||
// System.out.println(sss1);
|
||||
|
||||
refundOrder(null, new RefundParamsDto()
|
||||
.setMerchantId("1738216504")
|
||||
.setOrderNo("sa101293120sss1")
|
||||
.setTitle("1213")
|
||||
.setBody("1213")
|
||||
.setAmount(1L)
|
||||
.setAppId("wxd88fffa983758a30")
|
||||
.setClientIp("127.0.0.1")
|
||||
.setBarCode("130013153082460022"));
|
||||
.setRefundOrderNo("sa101293120sss1")
|
||||
.setOrderAmount(1L)
|
||||
.setRefundAmount(1L)
|
||||
.setRefundReason("测试")
|
||||
.setRefundNotifyUrl("https://www.baidu.com"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@ package com.czg.third.wechat;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.czg.dto.req.WechatNotifyReqDto;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.cipher.Signer;
|
||||
import com.wechat.pay.java.core.http.HttpClient;
|
||||
import com.wechat.pay.java.core.http.HttpMethod;
|
||||
import com.wechat.pay.java.core.util.NonceUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -16,7 +15,6 @@ import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -71,7 +69,7 @@ public class WechatReqUtils {
|
||||
log.info("微信支付请求:url = {} \nauthorization: {}", request.getUrl(), authorization);
|
||||
HttpResponse response = request.execute();
|
||||
String s = response.body();
|
||||
log.info("微信支付请求:url = {}\n\tmethod: {}\n\tbody: {}\n\tresp: {}", url, method, body, s);
|
||||
log.info("微信支付请求:\n\turl = {}\n\tmethod: {}\n\tbody: {}\n\tresp: {}", url, method, body, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -102,6 +100,28 @@ public class WechatReqUtils {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密微信回调报文
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param reqDto 请求报文
|
||||
* @return 解密后的报文
|
||||
*/
|
||||
public static String decryptRespParam(WechatPayConfigDto configDto, WechatNotifyReqDto reqDto) {
|
||||
if (configDto == null) {
|
||||
configDto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
WechatAesUtil aesUtil = new WechatAesUtil(configDto.getApiV3Key().getBytes(StandardCharsets.UTF_8));
|
||||
try {
|
||||
return aesUtil.decryptToString(
|
||||
reqDto.getResource().getAssociatedData() == null ? new byte[0] : reqDto.getResource().getAssociatedData().getBytes(StandardCharsets.UTF_8),
|
||||
reqDto.getResource().getNonce().getBytes(StandardCharsets.UTF_8), reqDto.getResource().getCiphertext());
|
||||
} catch (Exception e) {
|
||||
log.error("【微信支付回调】解密失败 {}", reqDto);
|
||||
throw new CzgException("解密失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机串
|
||||
*/
|
||||
|
||||
@@ -299,6 +299,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
orderDetails.forEach(item -> {
|
||||
item.setUrgent(true);
|
||||
item.setSubStatus(TableValueConstant.OrderDetail.SubStatus.READY_TO_SERVE.getCode());
|
||||
item.setStartOrderTime(DateUtil.date().toLocalDateTime());
|
||||
});
|
||||
} else {
|
||||
switch (EnumUtil.fromString(TableValueConstant.OrderDetail.SubStatus.class, param.getSubStatus())) {
|
||||
|
||||
@@ -100,15 +100,19 @@ public class ShopDirectMerchantServiceImpl extends ServiceImpl<ShopDirectMerchan
|
||||
merchant.setBusinessLicenceInfo(JSONObject.toJSONString(reqDto.getBusinessLicenceInfo()));
|
||||
merchant.setStoreInfo(JSONObject.toJSONString(reqDto.getStoreInfo()));
|
||||
merchant.setSettlementInfo(JSONObject.toJSONString(reqDto.getSettlementInfo()));
|
||||
if (merchant.getAlipayStatus().equals(PayCst.EntryStatus.INIT) || merchant.getAlipayStatus().equals(PayCst.EntryStatus.REJECTED)) {
|
||||
merchant.setAlipayStatus(PayCst.EntryStatus.WAIT);
|
||||
}
|
||||
if (merchant.getWechatStatus().equals(PayCst.EntryStatus.INIT) || merchant.getWechatStatus().equals(PayCst.EntryStatus.REJECTED)) {
|
||||
merchant.setWechatStatus(PayCst.EntryStatus.WAIT);
|
||||
}
|
||||
|
||||
if (isSave) {
|
||||
merchant.setAlipayStatus(PayCst.EntryStatus.WAIT);
|
||||
merchant.setWechatStatus(PayCst.EntryStatus.WAIT);
|
||||
result = save(merchant);
|
||||
} else {
|
||||
ShopDirectMerchant directMerchant = getById(reqDto.getShopId());
|
||||
if (directMerchant.getAlipayStatus().equals(PayCst.EntryStatus.INIT) || directMerchant.getAlipayStatus().equals(PayCst.EntryStatus.REJECTED)) {
|
||||
merchant.setAlipayStatus(PayCst.EntryStatus.WAIT);
|
||||
}
|
||||
if (directMerchant.getWechatStatus().equals(PayCst.EntryStatus.INIT) || directMerchant.getWechatStatus().equals(PayCst.EntryStatus.REJECTED)) {
|
||||
merchant.setWechatStatus(PayCst.EntryStatus.WAIT);
|
||||
}
|
||||
result = updateById(merchant);
|
||||
}
|
||||
//发送进件队列消息
|
||||
|
||||
Reference in New Issue
Block a user