mirror of
https://github.com/RemainderTime/spring-boot-base-demo.git
synced 2026-06-10 03:57:41 +08:00
新增微信支付以及支付宝工具类实现
This commit is contained in:
26
pom.xml
26
pom.xml
@@ -151,6 +151,24 @@
|
|||||||
<version>8.16.0</version>
|
<version>8.16.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--微信支付-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||||
|
<artifactId>wechatpay-java</artifactId>
|
||||||
|
<version>0.2.15</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||||
|
<artifactId>wechatpay-apache-httpclient</artifactId>
|
||||||
|
<version>0.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!--支付宝-->
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alipay.sdk</groupId>
|
||||||
|
<artifactId>alipay-sdk-java</artifactId>
|
||||||
|
<version>4.40.0.ALL</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
@@ -168,6 +186,14 @@
|
|||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>14</source>
|
||||||
|
<target>14</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package cn.xf.basedemo.common.model.pay;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlipayTransRsqVo {
|
||||||
|
private boolean success = false;
|
||||||
|
private String code;
|
||||||
|
private String subCode;
|
||||||
|
private String msg;
|
||||||
|
private String orderId;
|
||||||
|
private String status;
|
||||||
|
private String payFundOrderID;
|
||||||
|
private String outBizNo;
|
||||||
|
private String transDate;
|
||||||
|
private String settleSerialNo;
|
||||||
|
private String amount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cn.xf.basedemo.common.model.pay;
|
||||||
|
|
||||||
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RefundInfoRsqDTO {
|
||||||
|
|
||||||
|
private boolean isSuccess;
|
||||||
|
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
private Refund refund;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cn.xf.basedemo.common.model.pay;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TransferQueryVO {
|
||||||
|
|
||||||
|
private boolean isSuccess;
|
||||||
|
private String resCode;
|
||||||
|
private String resCodeDes;
|
||||||
|
private WechatCashQueryVo cashQueryVo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package cn.xf.basedemo.common.model.pay;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WechatCashQueryVo {
|
||||||
|
private String appid;
|
||||||
|
private String batch_id;
|
||||||
|
private String detail_id;
|
||||||
|
private String detail_status;
|
||||||
|
private OffsetDateTime initiate_time;
|
||||||
|
private String mchid;
|
||||||
|
private String openid;
|
||||||
|
private String out_batch_no;
|
||||||
|
private String out_detail_no;
|
||||||
|
private long transfer_amount;
|
||||||
|
private String transfer_remark;
|
||||||
|
private OffsetDateTime update_time;
|
||||||
|
private String user_name;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package cn.xf.basedemo.common.model.pay;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WxPayTransRsqVo {
|
||||||
|
private boolean success = false;
|
||||||
|
private String code;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
}
|
||||||
210
src/main/java/cn/xf/basedemo/common/utils/pay/AliPayUtil.java
Normal file
210
src/main/java/cn/xf/basedemo/common/utils/pay/AliPayUtil.java
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
package cn.xf.basedemo.common.utils.pay;
|
||||||
|
|
||||||
|
import cn.xf.basedemo.common.model.pay.AlipayTransRsqVo;
|
||||||
|
import com.alipay.api.AlipayApiException;
|
||||||
|
import com.alipay.api.AlipayClient;
|
||||||
|
import com.alipay.api.CertAlipayRequest;
|
||||||
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
|
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
|
||||||
|
import com.alipay.api.domain.Participant;
|
||||||
|
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
|
||||||
|
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class AliPayUtil {
|
||||||
|
|
||||||
|
//支付路径
|
||||||
|
private static String payPath;
|
||||||
|
private static PayInfo payInfo;
|
||||||
|
private static String gatewayUrl = "https://openapi.alipay.com/gateway.do";//"https://openapi.alipaydev.com/gateway.do";
|
||||||
|
private static String format = "json";
|
||||||
|
private static String charset = "utf-8";
|
||||||
|
private static String signType = "RSA2";
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class PayInfo {
|
||||||
|
String appId;
|
||||||
|
String appCertPath;
|
||||||
|
String alipayCertPath;
|
||||||
|
String rootCertPath;
|
||||||
|
String rsaPrivateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliPayUtil(String path) {
|
||||||
|
payPath = path;
|
||||||
|
String path1 = "d:/pay/";
|
||||||
|
path1 = "";
|
||||||
|
if (path.equals("a")) {
|
||||||
|
payInfo = new PayInfo();
|
||||||
|
payInfo.setAppId("");
|
||||||
|
payInfo.setAppCertPath(path1 + "15080.crt");
|
||||||
|
payInfo.setAlipayCertPath(path1 + "alipayCertPublicKey_RSA2.crt");
|
||||||
|
payInfo.setRootCertPath(path1 + "alipayRootCert.crt");
|
||||||
|
payInfo.setRsaPrivateKey(readFileContent(path1 + "private.key"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public AlipayTransRsqVo transfer(String trans_no, String account, BigDecimal money, int type, String trueName, String mark) {
|
||||||
|
AlipayTransRsqVo resVo = new AlipayTransRsqVo();
|
||||||
|
// 创建API客户端实例
|
||||||
|
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
|
||||||
|
certAlipayRequest.setServerUrl(gatewayUrl);
|
||||||
|
certAlipayRequest.setAppId(payInfo.appId);
|
||||||
|
certAlipayRequest.setPrivateKey(payInfo.rsaPrivateKey);
|
||||||
|
certAlipayRequest.setFormat(format);
|
||||||
|
certAlipayRequest.setCharset(charset);
|
||||||
|
certAlipayRequest.setSignType(signType);
|
||||||
|
//设置应用公钥证书路径
|
||||||
|
certAlipayRequest.setCertPath(payInfo.getAppCertPath());
|
||||||
|
//设置支付宝公钥证书路径
|
||||||
|
certAlipayRequest.setAlipayPublicCertPath(payInfo.alipayCertPath);
|
||||||
|
//certAlipayRequest.setAlipayPublicCertContent(AlipaySignature.getAlipayPublicKey(payInfo.alipayCertPath));
|
||||||
|
//设置支付宝根证书路径
|
||||||
|
certAlipayRequest.setRootCertPath(payInfo.getRootCertPath());
|
||||||
|
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||||
|
|
||||||
|
|
||||||
|
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称alipay.fund.trans.uni.transfer(单笔转账接口) **/
|
||||||
|
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
|
||||||
|
|
||||||
|
AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
|
||||||
|
|
||||||
|
/******必传参数******/
|
||||||
|
// 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一
|
||||||
|
model.setOutBizNo(trans_no);
|
||||||
|
|
||||||
|
// 转账金额,TRANS_ACCOUNT_NO_PWD产品取值最低0.1
|
||||||
|
model.setTransAmount(String.valueOf(money.setScale(2, RoundingMode.HALF_UP)));
|
||||||
|
|
||||||
|
// 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD。
|
||||||
|
model.setProductCode("TRANS_ACCOUNT_NO_PWD");
|
||||||
|
|
||||||
|
// 业务场景。单笔无密转账固定为 DIRECT_TRANSFER
|
||||||
|
model.setBizScene("DIRECT_TRANSFER");
|
||||||
|
|
||||||
|
// 转账业务的标题,用于在支付宝用户的账单里显示。
|
||||||
|
model.setOrderTitle("订单标题");
|
||||||
|
|
||||||
|
// 收款方信息
|
||||||
|
Participant payeeInfo = new Participant();
|
||||||
|
// 参与方的标识类型,设置ALIPAY_USER_ID或者ALIPAY_LOGON_ID
|
||||||
|
// ALIPAY_USER_ID:支付宝会员的用户 ID,可通过 获取会员信息 获取:https://opendocs.alipay.com/open/284/106000
|
||||||
|
// ALIPAY_LOGON_ID:支付宝登录号,支持邮箱和手机号格式。
|
||||||
|
if (type == 1) {
|
||||||
|
payeeInfo.setIdentityType("ALIPAY_USER_ID");
|
||||||
|
}
|
||||||
|
if (type == 2) {
|
||||||
|
payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 参与方的标识 ID,根据identity_type类型选择对应信息
|
||||||
|
// 当 identity_type=ALIPAY_USER_ID 时,填写支付宝用户 UID。示例值:2088123412341234。
|
||||||
|
// 当 identity_type=ALIPAY_LOGON_ID 时,填写支付宝登录号。示例值:186xxxxxxxx。
|
||||||
|
payeeInfo.setIdentity(account);
|
||||||
|
// 参与方真实姓名。如果非空,将校验收款支付宝账号姓名一致性。
|
||||||
|
// 当 identity_type=ALIPAY_LOGON_ID 时,本字段必填。
|
||||||
|
payeeInfo.setName(trueName);
|
||||||
|
model.setPayeeInfo(payeeInfo);
|
||||||
|
|
||||||
|
/******可选参数******/
|
||||||
|
// 业务备注
|
||||||
|
model.setRemark(mark);
|
||||||
|
|
||||||
|
// 转账业务请求的扩展参数
|
||||||
|
// payer_show_name_use_alias:是否展示付款方别名,可选,收款方在支付宝账单中可见。枚举支持:
|
||||||
|
// * true:展示别名,将展示商家支付宝在商家中心 商户信息 > 商户基本信息 页面配置的 商户别名。
|
||||||
|
// * false:不展示别名。默认为 false。
|
||||||
|
// model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
|
||||||
|
|
||||||
|
request.setBizModel(model);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 发送请求并获取响应
|
||||||
|
// AlipayFundTransToaccountTransferResponse response = alipayClient.certificateExecute(request);
|
||||||
|
AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
|
||||||
|
// 处理响应,通常需要检查out_biz_no,trade_no,和resultCode
|
||||||
|
if (response.isSuccess()) {
|
||||||
|
resVo.setSuccess(true);
|
||||||
|
resVo.setMsg(response.getSubMsg());
|
||||||
|
//resVo.setBody(JSON.parseObject(response.getBody(), AliPayBodyVo.class));
|
||||||
|
resVo.setOrderId(response.getOrderId());
|
||||||
|
resVo.setStatus(response.getStatus());
|
||||||
|
resVo.setPayFundOrderID(response.getPayFundOrderId());
|
||||||
|
resVo.setTransDate(response.getTransDate());
|
||||||
|
resVo.setOutBizNo(response.getOutBizNo());
|
||||||
|
resVo.setSettleSerialNo(response.getSettleSerialNo());
|
||||||
|
resVo.setAmount(response.getAmount());
|
||||||
|
|
||||||
|
|
||||||
|
log.info("转账成功: " + response.getBody());
|
||||||
|
} else {
|
||||||
|
resVo.setSuccess(false);
|
||||||
|
resVo.setMsg(response.getSubMsg());
|
||||||
|
resVo.setCode(response.getCode());
|
||||||
|
resVo.setSubCode(response.getSubCode());
|
||||||
|
log.info("转账失败: " + response.getSubCode() + " - " + response.getSubMsg());
|
||||||
|
}
|
||||||
|
} catch (AlipayApiException e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
resVo.setSuccess(false);
|
||||||
|
resVo.setMsg(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return resVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrivateKey getPrivateKeyFromPath(String path) {
|
||||||
|
try {
|
||||||
|
FileInputStream fis = new FileInputStream(path);
|
||||||
|
byte[] keyBytes = new byte[fis.available()];
|
||||||
|
fis.read(keyBytes);
|
||||||
|
fis.close();
|
||||||
|
|
||||||
|
String privateKeyPEM = new String(keyBytes);
|
||||||
|
// 移除PEM头部和尾部
|
||||||
|
privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "");
|
||||||
|
privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", "");
|
||||||
|
// 对于Windows平台,请使用"\r\n"作为分隔符;对于Linux/Mac平台,应使用"\n"
|
||||||
|
privateKeyPEM = privateKeyPEM.replaceAll("\\r\\n|\\n|\\r", "");
|
||||||
|
|
||||||
|
byte[] decoded = Base64.decodeBase64(privateKeyPEM);
|
||||||
|
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
|
||||||
|
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||||
|
|
||||||
|
return kf.generatePrivate(keySpec);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readFileContent(String filePath) {
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
content.append(line).append("\n");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return content.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
270
src/main/java/cn/xf/basedemo/common/utils/pay/WxPayUtil.java
Normal file
270
src/main/java/cn/xf/basedemo/common/utils/pay/WxPayUtil.java
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
package cn.xf.basedemo.common.utils.pay;
|
||||||
|
|
||||||
|
import cn.xf.basedemo.common.model.pay.RefundInfoRsqDTO;
|
||||||
|
import cn.xf.basedemo.common.model.pay.TransferQueryVO;
|
||||||
|
import cn.xf.basedemo.common.model.pay.WechatCashQueryVo;
|
||||||
|
import cn.xf.basedemo.common.model.pay.WxPayTransRsqVo;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.wechat.pay.java.core.Config;
|
||||||
|
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||||
|
import com.wechat.pay.java.core.exception.HttpException;
|
||||||
|
import com.wechat.pay.java.core.exception.MalformedMessageException;
|
||||||
|
import com.wechat.pay.java.core.exception.ServiceException;
|
||||||
|
import com.wechat.pay.java.service.refund.RefundService;
|
||||||
|
import com.wechat.pay.java.service.refund.model.AmountReq;
|
||||||
|
import com.wechat.pay.java.service.refund.model.CreateRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
|
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
|
||||||
|
import com.wechat.pay.java.service.transferbatch.model.*;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class WxPayUtil {
|
||||||
|
|
||||||
|
private static String payPath;
|
||||||
|
private static String appId;
|
||||||
|
private static String wxMerchantId;
|
||||||
|
private static String wxApiV3Key;
|
||||||
|
private static String wxApiSerialNo;
|
||||||
|
private static String wxMerchantApiCertificate;
|
||||||
|
private static String wxMerchantApiPrivateKey;
|
||||||
|
private static String plantSerialNo;
|
||||||
|
private static String notifyUrl; //通知URL
|
||||||
|
private static String refundUrl; //退款充值URL
|
||||||
|
|
||||||
|
public WxPayUtil(String path, int type) {
|
||||||
|
payPath = path;
|
||||||
|
type = type;
|
||||||
|
String path1 = "d:/pay";
|
||||||
|
path1 = "";
|
||||||
|
refundUrl = "" + payPath;
|
||||||
|
switch (payPath) {
|
||||||
|
case "a"://提现打款用-文撩
|
||||||
|
appId = "";
|
||||||
|
wxMerchantId = "";
|
||||||
|
wxApiV3Key = "";
|
||||||
|
wxApiSerialNo = "";
|
||||||
|
wxMerchantApiCertificate = path1 + "9DE56.pem";
|
||||||
|
wxMerchantApiPrivateKey = path1 + "apiclient_key.pem";
|
||||||
|
plantSerialNo = "1A1D8C3A474A29DE56";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public WxPayTransRsqVo transfer(String trans_no, String account, BigDecimal money, String trueName, String mark) {
|
||||||
|
WxPayTransRsqVo rsqVo = new WxPayTransRsqVo();
|
||||||
|
rsqVo.setSuccess(false);
|
||||||
|
log.info("开始退款,{}-{}-{}-{}-{}", wxMerchantId, wxMerchantApiPrivateKey, wxApiSerialNo, wxApiV3Key, money);
|
||||||
|
Config config = new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(wxMerchantId)
|
||||||
|
.privateKeyFromPath(wxMerchantApiPrivateKey)
|
||||||
|
.merchantSerialNumber(wxApiSerialNo)
|
||||||
|
.apiV3Key(wxApiV3Key)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
TransferBatchService service = new TransferBatchService.Builder().config(config).build();
|
||||||
|
//数据封装
|
||||||
|
InitiateBatchTransferRequest initiateBatchTransferRequest = new InitiateBatchTransferRequest();
|
||||||
|
initiateBatchTransferRequest.setAppid(appId);
|
||||||
|
initiateBatchTransferRequest.setOutBatchNo(trans_no);
|
||||||
|
initiateBatchTransferRequest.setBatchName(mark);
|
||||||
|
initiateBatchTransferRequest.setBatchRemark(mark);
|
||||||
|
initiateBatchTransferRequest.setTotalAmount(money.multiply(BigDecimal.valueOf(100)).longValue());
|
||||||
|
initiateBatchTransferRequest.setTotalNum(1);
|
||||||
|
|
||||||
|
//initiateBatchTransferRequest.setTransferSceneId("1001");
|
||||||
|
{
|
||||||
|
List<TransferDetailInput> transferDetailListList = new ArrayList<>();
|
||||||
|
{
|
||||||
|
TransferDetailInput transferDetailInput = new TransferDetailInput();
|
||||||
|
transferDetailInput.setTransferAmount(money.multiply(BigDecimal.valueOf(100)).longValue());//金额为分 需要乘以100
|
||||||
|
transferDetailInput.setOutDetailNo(trans_no);
|
||||||
|
transferDetailInput.setOpenid(account);
|
||||||
|
transferDetailInput.setUserName(trueName);
|
||||||
|
transferDetailInput.setTransferRemark(mark);
|
||||||
|
transferDetailListList.add(transferDetailInput);
|
||||||
|
}
|
||||||
|
initiateBatchTransferRequest.setTransferDetailList(
|
||||||
|
transferDetailListList);
|
||||||
|
}
|
||||||
|
//发起商家转账
|
||||||
|
InitiateBatchTransferResponse response;
|
||||||
|
try {
|
||||||
|
response = service.initiateBatchTransfer(initiateBatchTransferRequest);
|
||||||
|
log.info("转账:", response.toString());
|
||||||
|
// if (response.getBatchStatus().equals("ACCEPTED")) {
|
||||||
|
// log.info("initiateBatchTransfer:", response.getBatchStatus());
|
||||||
|
// }
|
||||||
|
// log.error("initiateBatchTransfer:", response.getBatchStatus());
|
||||||
|
rsqVo.setSuccess(true);
|
||||||
|
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
log.info("出错了:", e.getErrorMessage());
|
||||||
|
// e.printStackTrace();
|
||||||
|
|
||||||
|
|
||||||
|
rsqVo.setCode(e.getErrorCode());
|
||||||
|
rsqVo.setMsg(e.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rsqVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public TransferQueryVO transferQuery(String outBatchNo, String outDetailNo) {
|
||||||
|
TransferQueryVO transferQueryVO = new TransferQueryVO();
|
||||||
|
//商家转账批次单号
|
||||||
|
//商家转账明细单号
|
||||||
|
transferQueryVO.setSuccess(false);
|
||||||
|
Config config = new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(wxMerchantId)
|
||||||
|
.privateKeyFromPath(wxMerchantApiPrivateKey)
|
||||||
|
.merchantSerialNumber(wxApiSerialNo)
|
||||||
|
.apiV3Key(wxApiV3Key)
|
||||||
|
.build();
|
||||||
|
try {
|
||||||
|
TransferBatchService transferBatchService = new TransferBatchService.Builder().config(config).build();
|
||||||
|
GetTransferDetailByOutNoRequest request = new GetTransferDetailByOutNoRequest();
|
||||||
|
request.setOutBatchNo(outBatchNo);
|
||||||
|
request.setOutDetailNo(outDetailNo);
|
||||||
|
TransferDetailEntity response = transferBatchService.getTransferDetailByOutNo(request);
|
||||||
|
log.info("转账返回信息:{}", JSON.toJSONString(response));
|
||||||
|
transferQueryVO.setCashQueryVo(JSON.parseObject(JSON.toJSONString(response), WechatCashQueryVo.class));
|
||||||
|
transferQueryVO.setResCode(response.getDetailStatus());
|
||||||
|
transferQueryVO.setResCodeDes(response.getDetailStatus());
|
||||||
|
if ("FAIL".equals(response.getDetailStatus())) {
|
||||||
|
// transferQueryVO.setResCodeDes(getErrorMsg(String.valueOf(response.getFailReason())));
|
||||||
|
transferQueryVO.setSuccess(false);
|
||||||
|
} else {
|
||||||
|
transferQueryVO.setSuccess(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("转账返回信息II:{}", JSON.toJSONString(transferQueryVO));
|
||||||
|
} catch (HttpException e) { // 发送HTTP请求失败
|
||||||
|
// 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
|
||||||
|
log.error(e.getMessage());
|
||||||
|
transferQueryVO.setResCodeDes(e.getMessage());
|
||||||
|
// throw new RuntimeException("微信转账失败");
|
||||||
|
} catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
|
||||||
|
// 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
|
||||||
|
log.error(e.getMessage());
|
||||||
|
transferQueryVO.setResCodeDes(e.getMessage());
|
||||||
|
//throw new RuntimeException("微信转账失败");
|
||||||
|
} catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
|
||||||
|
// 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
|
||||||
|
log.error(e.getMessage());
|
||||||
|
transferQueryVO.setResCodeDes(e.getMessage());
|
||||||
|
//throw new RuntimeException("微信转账失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
// e.printStackTrace();
|
||||||
|
transferQueryVO.setResCodeDes(e.getMessage());
|
||||||
|
//throw new RuntimeException("微信转账失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return transferQueryVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public RefundInfoRsqDTO refundUser(String outTradeNo, String outRefundNo, long totalFee, BigDecimal refundFee) {
|
||||||
|
RefundInfoRsqDTO refundInfoRsqDTO = new RefundInfoRsqDTO();
|
||||||
|
refundInfoRsqDTO.setSuccess(false);
|
||||||
|
Config config = new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(wxMerchantId)
|
||||||
|
.privateKeyFromPath(wxMerchantApiPrivateKey)
|
||||||
|
.merchantSerialNumber(wxApiSerialNo)
|
||||||
|
.apiV3Key(wxApiV3Key)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
RefundService service = new RefundService.Builder().config(config).build();
|
||||||
|
CreateRequest request = new CreateRequest();
|
||||||
|
request.setOutTradeNo(outTradeNo);
|
||||||
|
request.setOutRefundNo(outRefundNo);
|
||||||
|
request.setNotifyUrl(refundUrl);
|
||||||
|
AmountReq amount = new AmountReq();
|
||||||
|
amount.setRefund(refundFee.longValue());
|
||||||
|
amount.setTotal(totalFee);
|
||||||
|
amount.setCurrency("CNY");
|
||||||
|
request.setAmount(amount);
|
||||||
|
try {
|
||||||
|
Refund refund = service.create(request);
|
||||||
|
log.info("refund:{}", refund.toString());
|
||||||
|
if (refund.getStatus().toString().equals("PROCESSING")) {
|
||||||
|
refundInfoRsqDTO.setSuccess(true);
|
||||||
|
}
|
||||||
|
refundInfoRsqDTO.setRefund(refund);
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
log.error("退款失败:{}------{}-----{}", e.getErrorMessage(), e.getErrorCode(), e.getResponseBody());
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
refundInfoRsqDTO.setMsg(e.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return refundInfoRsqDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefundInfoRsqDTO queryRefund(String outRefundNo) {
|
||||||
|
RefundInfoRsqDTO refundInfoRsqDTO = new RefundInfoRsqDTO();
|
||||||
|
refundInfoRsqDTO.setSuccess(false);
|
||||||
|
Config config = new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(wxMerchantId)
|
||||||
|
.privateKeyFromPath(wxMerchantApiPrivateKey)
|
||||||
|
.merchantSerialNumber(wxApiSerialNo)
|
||||||
|
.apiV3Key(wxApiV3Key)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
RefundService service = new RefundService.Builder().config(config).build();
|
||||||
|
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
|
||||||
|
request.setOutRefundNo(outRefundNo);
|
||||||
|
try {
|
||||||
|
Refund refund = service.queryByOutRefundNo(request);
|
||||||
|
log.info("refund:{}", refund.toString());
|
||||||
|
if (refund.getStatus().toString().equals("SUCCESS")) {
|
||||||
|
refundInfoRsqDTO.setSuccess(true);
|
||||||
|
}
|
||||||
|
refundInfoRsqDTO.setRefund(refund);
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
log.error("查询失败:{}------{}-----{}", e.getErrorMessage(), e.getErrorCode(), e.getResponseBody());
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
refundInfoRsqDTO.setMsg(e.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return refundInfoRsqDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private String getErrorMsg(String errCode) {
|
||||||
|
// return switch (errCode) {
|
||||||
|
// case "ACCOUNT_FROZEN" -> "账户冻结";
|
||||||
|
// case "REAL_NAME_CHECK_FAIL" -> "用户未实名";
|
||||||
|
// case "NAME_NOT_CORRECT" -> "用户姓名校验失败";
|
||||||
|
// case "OPENID_INVALID" -> "Openid校验失败";
|
||||||
|
// case "TRANSFER_QUOTA_EXCEED" -> "超过用户单笔收款额度";
|
||||||
|
// case "DAY_RECEIVED_QUOTA_EXCEED" -> "超过用户单日收款额度";
|
||||||
|
// case "MONTH_RECEIVED_QUOTA_EXCEED" -> "超过用户单月收款额度";
|
||||||
|
// case "DAY_RECEIVED_COUNT_EXCEED" -> "超过用户单日收款次数";
|
||||||
|
// case "PRODUCT_AUTH_CHECK_FAIL" -> "产品权限校验失败";
|
||||||
|
// case "OVERDUE_CLOSE" -> "转账关闭";
|
||||||
|
// case "ID_CARD_NOT_CORRECT" -> "用户身份证校验失败";
|
||||||
|
// case "ACCOUNT_NOT_EXIST" -> "用户账户不存在";
|
||||||
|
// case "TRANSFER_RISK" -> "转账存在风险";
|
||||||
|
// case "REALNAME_ACCOUNT_RECEIVED_QUOTA_EXCEED" -> "用户账户收款受限,请引导用户在微信支付查看详情";
|
||||||
|
// case "RECEIVE_ACCOUNT_NOT_PERMMIT" -> "未配置该用户为转账收款人";
|
||||||
|
// case "PAYER_ACCOUNT_ABNORMAL" -> "商户账户付款受限,可前往商户平台-违约记录获取解除功能限制指引";
|
||||||
|
// case "PAYEE_ACCOUNT_ABNORMAL" -> "用户账户收款异常,请引导用户完善其在微信支付的身份信息以继续收款";
|
||||||
|
// case "TRANSFER_REMARK_SET_FAIL" -> "转账备注设置失败,请调整对应文案后重新再试";
|
||||||
|
// default -> "内部错误,请联系管理人员";
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user