依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.7</version>
</dependency>
<!-- json -->
<!-- https://mvnrepository.com/artifact/org.json/json-simple string转为jsonobject-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.25</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.9</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.35.107.ALL</version>
</dependency>
微信部分:
密钥位置
controller
package com.wxpaydemo.controller;
import com.wxpaydemo.util.WXPayUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author xxs
* @date 2023年04月18日 21:11
*/
@Controller
@RequestMapping("/wxpay")
@ResponseBody
public class WxPayController {
@Resource
private WXPayUtil wxPayUtil;
// 得到二维码
@PostMapping("/wxPay")
public Map<String, Object> pay(@RequestBody Map<String,Object> map) {
return wxPayUtil.wxPay(map);
}
// 查询微信订单
@PostMapping("/wxPayQueryWx")
public Map<String, Object> queryWXOrderId(@RequestBody Map<String,Object> map) {
if (map==null||map.get("orderId")==null||map.get("orderId")==""){
Map<String, Object> res = new HashMap<>();
return wxPayUtil.ResultError("参数错误",null);
}
Map<String, Object> res = wxPayUtil.wxPayQueryWx(map.get("orderId")+"");
return res;
}
// 查询商户订单
@PostMapping("/wxPayQueryMy")
public Map<String, Object> queryMyOrderId(@RequestBody Map<String,Object> map) {
if (map==null||map.get("orderId")==null||map.get("orderId")==""){
Map<String, Object> res = new HashMap<>();
return wxPayUtil.ResultError("参数错误",null);
}
Map<String, Object> res = wxPayUtil.wxPayQueryMy(map.get("orderId")+"");
return res;
}
// 关单
@PostMapping("/closeWXOrder")
public Map<String, Object> closeOrderId(@RequestBody Map<String,Object> map) {
if (map==null||map.get("orderId")==null||map.get("orderId")==""){
Map<String, Object> res = new HashMap<>();
return wxPayUtil.ResultError("参数错误",null);
}
Map<String, Object> res = wxPayUtil.closeWXOrder(map.get("orderId")+"");
return res;
}
// 支付回调
@PostMapping("/wxPayNotify")
public Map<String, Object> notify(HttpServletRequest request, HttpServletResponse response) {
return wxPayUtil.wxPayNotify(request,response);
}
// 退款回调
@PostMapping("/wxPayReFundNotify")
public Map<String, Object> refundNotify(HttpServletRequest request, HttpServletResponse response) {
return wxPayUtil.wxPayReFundNotify(request,response);
}
/**
* @Author huxueyang
* @date 2023/4/19 15:50
* 需要传入原微信支付订单号或者原商户订单号
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
@PostMapping("/wxPayRefund")
public Map<String, Object> refund(@RequestBody Map<String,Object> map) {
return wxPayUtil.wxPayRefund(map);
}
/**
* @Author huxueyang
* 退款状态查询
* 需要传入退款单号
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
@PostMapping("/wxPayRefundQuery")
public Map<String, Object> refundQuery(@RequestBody Map<String,Object> map) {
return wxPayUtil.wxPayRefundQuery(map);
}
}
WXPayUtil
package com.wxpaydemo.util;/**
* @author husong
* @create 2023-04-19 15:34
*/
import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.*;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.*;
import com.wxpaydemo.config.WxPayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*@author huxueyang
* 用于微信支付,退款,查询等相关操作
*@dare 2023/4/19 15:34
*/
@Component
@Slf4j
public class WXPayUtil {
private final WXPayService wxPayService;
public final NativePayService nativePayService;
public final NotificationParser notificationParser;
public final RefundService refundService;
public WXPayUtil() {
this.wxPayService = new WXPayService();
this.nativePayService = wxPayService.getNativePayService();
this.notificationParser = wxPayService.getParse();
this.refundService = wxPayService.getRefundService();
}
/**
* 需要包含字段total,即订单金额(单位为分),description,订单描述
* 返回url:二维码网址,orderId:订单ID
**/
public Map<String ,Object> wxPay(Map<String, Object> map) {
if (map==null||!CommonUtils.validateNoNull(map.get("total"),map.get("description"))){
return ResultError("参数错误",null);
}
Map<String, Object> result = new HashMap<>();
// 订单号
long orderId = Long.parseLong(UUID.randomUUID().toString().replace("-", ""));
PrepayRequest request = new PrepayRequest();
//设置金额描述等信息
Amount amount = new Amount();
amount.setTotal(Integer.parseInt(map.get("total")+""));
amount.setCurrency("CNY");
request.setAmount(amount);
request.setNotifyUrl(WxPayConfig.notify_url);
//设置描述
request.setDescription(map.get("description")+"");
request.setAppid(WxPayConfig.appid);
request.setMchid(WxPayConfig.mch_id);
request.setNotifyUrl(WxPayConfig.notify_url);
request.setOutTradeNo(orderId+"");
PrepayResponse response=new PrepayResponse();
// 调用下单方法,得到应答
try {
response = nativePayService.prepay(request);
//url为二维码网址
HashMap<String, Object> payRes = new HashMap<>();
payRes.put("url",response.getCodeUrl());
payRes.put("orderId", orderId);
return ResultOk(payRes);
} catch (Exception e) {
log.error("请求错误-->{}",e);
return ResultError("请求错误",e);
}
}
/**
*
* 微信订单查询。需要插入微信支付订单号,返回值result。
**/
public Map wxPayQueryWx(String orderId){
if (orderId==null||orderId==""){
return ResultError("参数错误",null);
}
QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest();
queryRequest.setMchid(WxPayConfig.mch_id);
//插入查询订单号
queryRequest.setTransactionId(orderId);
try {
Transaction result = nativePayService.queryOrderById(queryRequest);
return ResultOk(result);
} catch (ServiceException e) {
// API返回失败, 例如ORDER_NOT_EXISTS
Map<String, Object> queryRes = new HashMap<>();
queryRes.put("errorCode",e.getErrorCode());
queryRes.put("msg",e.getErrorMessage());
return ResultError("查询失败",queryRes);
}
}
/**
* 商家订单查询。需要传入商家订单号,返回值result。
**/
public Map wxPayQueryMy(String orderId ){
if (orderId==null||orderId==""){
return ResultError("参数错误",null);
}
HashMap<String, Object> map = new HashMap<>();
QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
queryRequest.setMchid(WxPayConfig.mch_id);
//为商家订单号
queryRequest.setOutTradeNo(orderId);
try {
Transaction result = nativePayService.queryOrderByOutTradeNo(queryRequest);
return ResultOk(result);
} catch (ServiceException e) {
// API返回失败, 例如ORDER_NOT_EXISTS
Map<String, Object> queryRes = new HashMap<>();
queryRes.put("errorCode",e.getErrorCode());
queryRes.put("msg",e.getErrorMessage());
return ResultError("查询失败",queryRes);
}
}
/**
*关单。需要传入商家订单号,返回值result。msg为错误提示
* @return java.util.Map
**/
public Map closeWXOrder(String orderId){
if (orderId==null||orderId==""){
return ResultError("参数错误",null);
}
HashMap<String, Object> map = new HashMap<>();
CloseOrderRequest queryRequest = new CloseOrderRequest();
queryRequest.setMchid(WxPayConfig.mch_id);
queryRequest.setOutTradeNo(orderId);
try {
nativePayService.closeOrder(queryRequest);
return ResultOk("成功关单");
} catch (ServiceException e) {
Map<String, Object> closeRes = new HashMap<>();
closeRes.put("errorCode",e.getErrorCode());
closeRes.put("msg",e.getErrorMessage());
return ResultError("关单失败",closeRes);
}
}
/**
* @Author huxueyang
* 支付回调通知
**/
public Map<String, Object> wxPayNotify(HttpServletRequest request, HttpServletResponse response) {
HashMap<String, Object> map = new HashMap<>();
try {
//获取回调参数中的信息
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL))
.nonce(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE))
.signature(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE))
.timestamp(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP))
.body(CommonUtils.getBody(request))
.build();
//解密
Transaction parse =notificationParser.parse(requestParam, Transaction.class);
System.out.println(parse);
Map<String, Object> stringObjectMap = ResultOk(null);
//成功则响应SUCCESS
stringObjectMap.put("code","SUCCESS");
return stringObjectMap;
} catch (IOException e) {
return ResultError("系统异常",e);
}
}
/**
* @Author huxueyang
* 退款回调通知
**/
public Map<String, Object> wxPayReFundNotify(HttpServletRequest request, HttpServletResponse response) {
HashMap<String, Object> map = new HashMap<>();
try {
//获取回调参数中的信息
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL))
.nonce(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE))
.signature(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE))
.timestamp(request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP))
.body(CommonUtils.getBody(request))
.build();
//解密
RefundNotification parse = notificationParser.parse(requestParam, RefundNotification.class);
System.out.println(parse);
Map<String, Object> stringObjectMap = ResultOk(null);
//成功则响应SUCCESS
stringObjectMap.put("code","SUCCESS");
return stringObjectMap;
} catch (IOException e) {
return ResultError("系统异常",e);
}
}
/**
* @Author huxueyang
* 微信退款
* 需要包含字段total,即订单总金额,refund:当次退款金额,单位分,orderId:订单id
* 可含reason,退款原因
**/
public Map<String ,Object> wxPayRefund(Map<String, Object> map) {
HashMap<String, Object> result = new HashMap<>();
if (map==null||!CommonUtils.validateNoNull(map.get("orderId"),map.get("refund"),map.get("total"))){
return ResultError("参数错误",null);
}
String orderId = map.get("orderId")+"";
long refundId = Long.parseLong(UUID.randomUUID().toString().replace("-", ""));
log.error("支付单号{}-->退款单号{}",orderId,refundId);
CreateRequest createRequest = new CreateRequest();
//创建退款金额信息
AmountReq amountReq = new AmountReq();
amountReq.setCurrency("CNY");
amountReq.setRefund(Long.parseLong(map.get("refund")+""));
amountReq.setTotal(Long.parseLong(map.get("total")+""));
createRequest.setAmount(amountReq);
createRequest.setOutRefundNo(refundId+"");
createRequest.setOutTradeNo(orderId);
createRequest.setReason(map.get("reason")+"");
createRequest.setNotifyUrl(WxPayConfig.refund_notify_url);
Refund refund = null;
try {
refund = refundService.create(createRequest);
return ResultOk(refund);
} catch (Exception e) {
log.error("订单{}退款失败--->原因{}",orderId,e);
return ResultError("退款失败",e);
}
}
/**
* @Author huxueyang
* 查询订单退款状态,需要传入退款单号refundId
**/
public Map<String, Object> wxPayRefundQuery(Map<String, Object> map) {
if (map==null||map.get("refundId")==null||map.get("refundId")==""){
return ResultError("参数错误",null);
}
String refundId = map.get("refundId") + "";
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
request.setOutRefundNo(refundId);
Refund refund = null;
try {
refund = refundService.queryByOutRefundNo(request);
return ResultOk(refund);
} catch (Exception e) {
log.error("退款订单{}查询状态失败--->原因{}",refundId,e);
return ResultError("查询失败",e);
}
}
public Map<String, Object> ResultOk(Object data) {
Map<String, Object> map = new HashMap<>();
map.put("status",200);
map.put("result",data);
return map;
}
public Map<String, Object> ResultError(String message,Object data) {
Map<String, Object> map = new HashMap<>();
map.put("status",500);
map.put("message",message);
map.put("result",data);
return map;
}
}
WXPAYSERVice
package com.wxpaydemo.util;/**
* @author husong
* @create 2023-04-19 11:27
*/
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.refund.RefundService;
import com.wxpaydemo.config.WxPayConfig;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
*@author huxueyang
* 这些为单实例
* 用于向微信发请求
*@dare 2023/4/19 11:27
*/
@Data
@Slf4j
public class WXPayService {
//支付对象
public final NativePayService nativePayService;
//解析返回数据对象
public final NotificationParser parse;
//退款对象
public final RefundService refundService;
public WXPayService() {
// WxPayConfig wxPayConfig = new WxPayConfig();
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(WxPayConfig.mch_id)
.privateKeyFromPath(WxPayConfig.privateKeyPath)
.merchantSerialNumber(WxPayConfig.merchantSerialNumber)
.apiV3Key(WxPayConfig.apiV3Key)
.build();
// 构建service
this.nativePayService = new NativePayService.Builder().config(config).build();
this.parse = new NotificationParser((NotificationConfig)config);
this.refundService = new RefundService.Builder().config(config).build();
}
}
支付宝部分:
controller
package com.wxpaydemo.controller;/**
* @author husong
* @create 2023-04-20 9:24
*/
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.wxpaydemo.config.AlipayConfig;
import com.wxpaydemo.util.ZFBPayUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
*@author huxueyang
*@dare 2023/4/20 9:24
*/
@Controller
@RequestMapping("/zfbpay")
@ResponseBody
public class ZFBPayController {
@Resource
private ZFBPayUtil zfbPayUtil;
// 支付宝下单
@PostMapping("/zfbPay")
public Map<String, Object> pay(@RequestBody Map<String,Object> map) {
return zfbPayUtil.zfbPay(map);
}
// 查询支付宝订单订单
@PostMapping("/zfbPayQuery")
public Map<String, Object> queryMyOrderId(@RequestBody Map<String,Object> map) {
return zfbPayUtil.zfbPayQuery(map);
}
// 支付宝关单
@PostMapping("/closeZfbOrder")
public Map<String, Object> closeOrderId(@RequestBody Map<String,Object> map) {
return zfbPayUtil.closeZfbOrder(map);
}
// 支付回调,退款回调等
@PostMapping("/zfbNotify")
public Map<String, Object> notify(@RequestParam Map<String, String> params) {
return zfbPayUtil.zfbNotify(params);
}
//退款
@PostMapping("/zfbRefund")
public Map<String, Object> refund(@RequestBody Map<String,Object> map) {
return zfbPayUtil.zfbRefund(map);
}
//支付宝退款查询
@PostMapping("/zfbRefundQuery")
public Map<String, Object> refundQuery(@RequestBody Map<String,Object> map) {
return zfbPayUtil.zfbRefundQuery(map);
}
}
ZFBPAYUtil
package com.wxpaydemo.util;/**
* @author husong
* @create 2023-04-20 9:24
*/
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.wxpaydemo.config.AlipayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*@author huxueyang
*@dare 2023/4/20 9:24
*/
@Component
@Slf4j
public class ZFBPayUtil {
private AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.serverUrl,AlipayConfig.app_id,AlipayConfig.merchant_private_key,"json",AlipayConfig.charset,AlipayConfig.alipay_public_key,AlipayConfig.sign_type);
/**
* @Author huxueyang
* 支付宝下单接口
* 必填:total_amount(金额),subject(标题)
* 可选:time_expire(过期时间)等
* @return
**/
public Map<String, Object> zfbPay(Map<String,Object> map){
if (map==null||!CommonUtils.validateNoNull(map.get("total_amount"),map.get("subject"))){
return ResultError("参数错误",null);
}
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
//设置回调通知地址和支付后返回地址
request.setNotifyUrl(AlipayConfig.notify_url);
request.setReturnUrl(AlipayConfig.return_url);
JSONObject bizContent = new JSONObject();
//支付单号
long orderId = Long.parseLong(UUID.randomUUID().toString().replace("-", ""));
// //此两项来自自己
bizContent.put("out_trade_no", orderId);
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
//copy传入的其他参数
CommonUtils.copyMap(map,bizContent);
request.setBizContent(bizContent.toString());
AlipayTradePagePayResponse response = null;
try {
response = alipayClient.pageExecute(request);
} catch (AlipayApiException e) {
log.error("创建支付宝订单失败--->"+e);
return ResultError("创建支付宝订单失败失败",e);
}
if(response.isSuccess()){
log.info("创建支付宝订单成功{}--->",orderId);
Map<String, Object> stringObjectMap = ResultOk(response.getBody());
stringObjectMap.put("orderId",orderId);
return stringObjectMap;
} else {
Map<String, Object> resultError = ResultError("创建支付宝订单失败失败", response);
log.info("创建支付宝订单失败--->"+resultError);
return resultError;
}
}
/**
* @Author huxueyang
* 支付宝下单查询接口
* 必填:trade_no(支付宝交易号),out_trade_no(商家订单号)(有一个即可)
* @return
**/
public Map<String, Object> zfbPayQuery(Map<String,Object> map){
if (map==null||!CommonUtils.validateOne(map.get("trade_no"),map.get("out_trade_no"))){
return ResultError("请传入查询单号",null);
}
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
boolean flag=false;
//拼接参数
String bizContent="{";
if (!(map.get("trade_no")==null||map.get("trade_no")=="")){
flag=true;
bizContent=bizContent+"\"trade_no\":\""+map.get("trade_no")+"\"";
}
if (!(map.get("out_trade_no")==null||map.get("out_trade_no")=="")){
if (flag) {
bizContent=bizContent+",";
}
bizContent=bizContent+"\"out_trade_no\":\""+map.get("out_trade_no")+"\"";
}
bizContent=bizContent+" ,\"query_options\":[" +
" \"trade_settle_info\"" +
" ]" +
"}";
request.setBizContent(bizContent);
AlipayTradeQueryResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
log.error("查询支付宝订单失败--->"+e);
return ResultError("查询支付宝订单失败失败",e);
}
if(response.isSuccess()){
Map<String, Object> resultOk = ResultOk(response);
log.info("查询支付宝订单成功--->",resultOk);
return resultOk;
} else {
Map<String, Object> resultError = ResultError("查询支付宝订单失败失败", response);
log.info("查询支付宝订单失败{}",resultError);
return resultError;
}
} /**
* @Author huxueyang
* 支付宝退款接口
* 必填:trade_no(支付宝交易号),out_trade_no(商家订单号)(有一个即可) refund_amount(退款金额,单位元)
* 可选 out_request_no(退款请求号。标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传)
* @return
**/
public Map<String, Object> zfbRefund(Map<String,Object> map){
//校验
if (map==null||!CommonUtils.validateOne(map.get("out_trade_no"),map.get("trade_no"))||!CommonUtils.validateOne(map.get("refund_amount"))){
return ResultError("参数错误",null);
}
//构造请求参数
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
JSONObject bizContent = new JSONObject();
if (CommonUtils.validateNoNull(map.get("out_trade_no"))){
bizContent.put("out_trade_no", map.get("out_trade_no"));
}
if (CommonUtils.validateNoNull(map.get("trade_no"))){
bizContent.put("trade_no", map.get("trade_no"));
}
if (CommonUtils.validateNoNull(map.get("out_request_no"))){
bizContent.put("out_request_no", map.get("out_request_no"));
}
bizContent.put("refund_amount", map.get("refund_amount"));
CommonUtils.copyMap(map,bizContent);
request.setBizContent(bizContent.toString());
AlipayTradeRefundResponse response = null;
//发请求
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
log.error("支付宝订单退款失败--->"+e);
return ResultError("支付宝订单退款失败",e);
}
if(response.isSuccess()){
Map<String, Object> resultOk = ResultOk(response);
log.info("支付宝订单退款成功商户单号{},支付宝单号{},请求号{},退款金额,已退款金额{}",map.get("out_trade_no"),map.get("trade_no"),map.get("out_request_no"),map.get("refund_amount"),response.getRefundFee());
return resultOk;
} else {
Map<String, Object> resultError = ResultError("支付宝订单退款失败", response);
log.info("支付宝订单退款失败商户单号{},支付宝单号{},请求号{},退款金额{}",map.get("out_trade_no"),map.get("trade_no"),map.get("out_request_no"), map.get("refund_amount"));
log.info("支付宝订单退款失败信息",resultError);
return ResultError("支付宝订单退款失败",response);
}
}
/* @Author huxueyang
* @date 2023/4/20 9:27
* 支付宝退款查询接口
* 必填:trade_no(支付宝交易号),out_trade_no(商家订单号)(有一个即可)
* out_request_no(退款请求号。请求退款接口时,传入的退款请求号,如果在退款请求时未传入,则该值为创建交易时的商户订单号)
**/
public Map<String, Object> zfbRefundQuery(Map<String,Object> map){
//校验
if (!CommonUtils.validateOne(map.get("out_trade_no"),map.get("trade_no"))||!CommonUtils.validateOne(map.get("out_request_no"))){
return ResultError("参数错误",null);
}
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
JSONObject bizContent = new JSONObject();
if (CommonUtils.validateNoNull(map.get("out_trade_no"))){
bizContent.put("out_trade_no", map.get("out_trade_no"));
}
if (CommonUtils.validateNoNull(map.get("trade_no"))){
bizContent.put("trade_no", map.get("trade_no"));
}
bizContent.put("out_request_no", map.get("out_request_no"));
CommonUtils.copyMap(map,bizContent);
request.setBizContent(bizContent.toString());
AlipayTradeFastpayRefundQueryResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
log.error("支付宝退款订单查询失败--->"+e);
return ResultError("支付宝退款订单查询失败",e);
}
if(response.isSuccess()){
Map<String, Object> resultOk = ResultOk(response);
log.info("支付宝退款订单查询成功--->"+resultOk);
return ResultOk(response.getBody());
} else {
Map<String, Object> resultError = ResultError("支付宝退款订单查询失败", response);
log.info("支付宝退款订单查询失败--->"+resultError);
return resultError;
}
}
/* @Author huxueyang
* @date 2023/4/20 9:27
* 支付宝关单
* 必填:trade_no(支付宝交易号),out_trade_no(商家订单号)(有一个即可)
**/
public Map<String, Object> closeZfbOrder(Map<String,Object> map){
//校验
if (!CommonUtils.validateOne(map.get("out_trade_no"),map.get("trade_no"))){
return ResultError("参数错误",null);
}
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
JSONObject bizContent = new JSONObject();
if (CommonUtils.validateNoNull(map.get("out_trade_no"))){
bizContent.put("out_trade_no", map.get("out_trade_no"));
}
if (CommonUtils.validateNoNull(map.get("trade_no"))){
bizContent.put("trade_no", map.get("trade_no"));
}
CommonUtils.copyMap(map,bizContent);
request.setBizContent(bizContent.toString());
AlipayTradeCloseResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
log.error("支付宝订单关单失败--->"+e);
return ResultError("支付宝订单关单失败",e);
}
if(response.isSuccess()){
Map<String, Object> resultOk = ResultOk(response.getBody());
log.info("支付宝订单关单成功-->{}",resultOk);
return resultOk;
} else {
Map<String, Object> resultError = ResultError("支付宝订单关单失败", response);
log.info("支付宝订单关单失败--->{}",resultError);
return resultError;
}
}
/* @Author huxueyang
* 支付宝回调通知(支付回调退款回调)
**/
public Map<String, Object> zfbNotify(Map<String, String> params){
Map<String,Object> resultMap = new HashMap<>();
//异步通知验签
boolean signVerified = false; //调用SDK验证签名
try {
signVerified = AlipaySignature.rsaCheckV1(
params,
AlipayConfig.alipay_public_key,
AlipayConfig.charset,
AlipayConfig.sign_type
);
} catch (AlipayApiException e) {
throw new RuntimeException(e);
}
if(!signVerified){
//验签失败则记录异常日志,并在response中返回failure.
resultMap.put("status", 500);
return resultMap;
}
// 验签成功后
String appIdProperty = AlipayConfig.app_id;
String tradeStatus = params.get("trade_status");
resultMap.put("appIdProperty",appIdProperty);
resultMap.put("tradeStatus",tradeStatus);
resultMap.put("status", 200);
return resultMap;
}
public Map<String, Object> ResultOk(Object data) {
Map<String, Object> map = new HashMap<>();
map.put("status",200);
map.put("result",data);
return map;
}
public Map<String, Object> ResultError(String message,Object data) {
Map<String, Object> map = new HashMap<>();
map.put("status",500);
map.put("message",message);
map.put("result",data);
return map;
}
}
代码中封装功能类:
package com.wxpaydemo.util;/**
* @author husong
* @create 2023-04-19 15:07
*/
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Set;
/**
*@author huxueyang
*@dare 2023/4/19 15:07
*/
public class CommonUtils {
//微信支付回调通知获取参数
public static String getBody(HttpServletRequest request) throws IOException {
StringBuilder requestBody = new StringBuilder();
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) != -1) {
requestBody.append(charBuffer, 0, bytesRead);
}
}
String requestBodyStr = requestBody.toString();
return requestBodyStr;
}
public static String copyMap(Map<String,Object> source,Map<String,Object> target){
if (source==null||target==null){
return "参数错误";
}
Set<String> strings = source.keySet();
for (String string : strings) {
if (target.get("string")==null||target.get("string")==""){
target.put(string,source.get(string));
}
}
return "成功";
}
//都不为空为空返回true
public static boolean validateNoNull(Object ...data){
for (Object datum : data) {
if (datum==null||datum==""){
return false;
}
}
return true;
}
//有一个不为空为空返回true
public static boolean validateOne(Object ...data){
for (Object datum : data) {
if (!(datum==null||datum=="")){
return true;
}
}
return false;
}
}