maven引入
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>3.7.4.AL</version></dependency>
配置
package com.hyt.mall.pay.web.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
-
@author zww
-
@Description:
-
@date 2022/9/14 11:13
*/
@Configuration
@PropertySource("classpath:alipay.properties")
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig {
public static String appId;
public static String privateKey;
public static String publicKey;
public static String notifyUrl;
public static String returnUrl;
public static String url;
public static String charset;
public static String format;
public static String alipayPublicKey;
public static String signType;
public static String queryUrl;
public static String refundUrl;
public static String queryRefundUrl;
public static String closeUrl;public String getAppId() {
return appId;
}public void setAppId(String appId) {
AlipayConfig.appId = appId;
}public String getPrivateKey() {
return privateKey;
}public void setPrivateKey(String privateKey) {
AlipayConfig.privateKey = privateKey;
}public String getPublicKey() {
return publicKey;
}public void setPublicKey(String publicKey) {
AlipayConfig.publicKey = publicKey;
}public String getNotifyUrl() {
return notifyUrl;
}public void setNotifyUrl(String notifyUrl) {
AlipayConfig.notifyUrl = notifyUrl;
}public String getReturnUrl() {
return returnUrl;
}public void setReturnUrl(String returnUrl) {
AlipayConfig.returnUrl = returnUrl;
}public String getUrl() {
return url;
}public void setUrl(String url) {
AlipayConfig.url = url;
}public String getCharset() {
return charset;
}public void setCharset(String charset) {
AlipayConfig.charset = charset;
}public String getFormat() {
return format;
}public void setFormat(String format) {
AlipayConfig.format = format;
}public String getAlipayPublicKey() {
return alipayPublicKey;
}public void setAlipayPublicKey(String alipayPublicKey) {
AlipayConfig.alipayPublicKey = alipayPublicKey;
}public String getSignType() {
return signType;
}public void setSignType(String signType) {
AlipayConfig.signType = signType;
}public String getQueryUrl() {
return queryUrl;
}public void setQueryUrl(String queryUrl) {
AlipayConfig.queryUrl = queryUrl;
}public String getRefundUrl() {
return refundUrl;
}public void setRefundUrl(String refundUrl) {
AlipayConfig.refundUrl = refundUrl;
}public String getQueryRefundUrl() {
return queryRefundUrl;
}public void setQueryRefundUrl(String queryRefundUrl) {
AlipayConfig.queryRefundUrl = queryRefundUrl;
}public String getCloseUrl() {
return closeUrl;
}public void setCloseUrl(String closeUrl) {
AlipayConfig.closeUrl = closeUrl;
}
}
实现类
package com.hyt.mall.pay.web.service.impl.alipay;
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.hyt.mall.pay.web.config.AlipayConfig;
import com.hyt.mall.pay.web.req.OrderQueryReq;
import com.hyt.mall.pay.web.req.OrderRefundReq;
import com.hyt.mall.pay.web.req.OrderPayReq;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
-
@author zww
-
@Description:
-
@date 2022/9/14 13:19
*/
@Service
public class AlipayServiceImpl {private static final Logger LOG = LoggerFactory.getLogger(AlipayServiceImpl.class);
private AlipayClient alipayClient() {
return new DefaultAlipayClient(AlipayConfig.url,AlipayConfig.appId,AlipayConfig.privateKey,
AlipayConfig.format,AlipayConfig.charset,AlipayConfig.alipayPublicKey,AlipayConfig.signType);
}/**
- 支付接口
- @return string
*/
public String pay(OrderPayReq param) {
LOG.info("支付参数:{}", param.toString());
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl(AlipayConfig.notifyUrl);
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", param.getOrderNo());
bizContent.put("total_amount", param.getAmount());
bizContent.put("subject", param.getGoodsTitle());
//bizContent.put("product_code", "QUICK_MSECURITY_PAY");
request.setBizContent(bizContent.toString());
try {
AlipayTradeAppPayResponse response = alipayClient().sdkExecute(request);
if(response.isSuccess()){
return response.getBody();
} else {
return "error";
}
} catch (AlipayApiException e) {
LOG.error("支付调用异常:{}", e.getMessage());
return "error";
}
}
/**
- 统一收单线下交易查询
- @return string
*/
public String query(OrderQueryReq param) {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", param.getOrderNo());
//bizContent.put("trade_no", "2014112611001004680073956707");
request.setBizContent(bizContent.toString());
try {
AlipayTradeQueryResponse response = alipayClient().execute(request);
if(response.isSuccess()){
return "success";
} else {
return "error";
}
} catch (AlipayApiException e) {
LOG.error("交易查询调用异常:{}", e.getMessage());
return "error";
}
}
/**
-
统一收单交易退款接口
-
@return string
*/
public String refund(OrderRefundReq param) {
LOG.info("退款参数:{}", param.toString());
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", param.getOrderNo());
bizContent.put("refund_amount", param.getRefund());
bizContent.put("out_request_no", param.getRefundNo());
//bizContent.put("refund_reason", param.getReason());//// 返回参数选项,按需传入
//JSONArray queryOptions = new JSONArray();
//queryOptions.add("refund_detail_item_list");
//bizContent.put("query_options", queryOptions);request.setBizContent(bizContent.toString());
try {
AlipayTradeRefundResponse response = alipayClient().execute(request);
//JSONObject obj = (JSONObject) JSONObject.parse(JSON.toJSONString(response));
if(response.isSuccess()){
return "success";
} else {
return "error";
}
} catch (AlipayApiException e) {
LOG.error("退款调用异常:{}", e.getMessage());
return "error";
}
}
/**
-
统一收单交易退款查询
-
@return string
*/
public String refundQuery(Map<String, Object> param) {
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", param.get("order_no"));
bizContent.put("out_request_no", param.get("out_request_no"));//// 返回参数选项,按需传入
//JSONArray queryOptions = new JSONArray();
//queryOptions.add("refund_detail_item_list");
//bizContent.put("query_options", queryOptions);request.setBizContent(bizContent.toString());
try {
AlipayTradeFastpayRefundQueryResponse response = alipayClient().execute(request);
if(response.isSuccess()){
return "success";
} else {
return "error";
}
} catch (AlipayApiException e) {
LOG.error("易退款查询调用异常:{}", e.getMessage());
return "error";
}
}
/**
- 统一收单交易关闭接口
- @return string
*/
public String close(OrderQueryReq param) {
LOG.info("关闭参数:{}", param.toString());
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", param.getOrderNo());
request.setBizContent(bizContent.toString());
try {
AlipayTradeCloseResponse response = alipayClient().execute(request);
if(response.isSuccess()){
return "success";
} else {
return "error";
}
} catch (AlipayApiException e) {
LOG.error("关闭调用异常:{}", e.getMessage());
return "error";
}
}
public String notify(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> params = new HashMap<String, String>();
try {
//从支付宝回调的request域中取值
Map<String, String[]> requestParams = request.getParameterMap();
for (Iteratoriter = requestParams.keySet().iterator(); iter.hasNext()😉 {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
//商品订单号
String out_trade_no = request.getParameter("out_trade_no"); // 商户订单号
// 当前交易状态
String tradeStatus = request.getParameter("trade_status"); //交易状态
// 支付金额
String totalAmount = request.getParameter("total_amount"); //交易状态
// 支付时间
String payDate = request.getParameter("gmt_payment"); //交易状态
//3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的)调用SDK验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipayPublicKey, AlipayConfig.charset, AlipayConfig.signType);
//返回状态存入redis中
//对验签进行处理
if (signVerified) {
//验签通过
if(tradeStatus.equals("TRADE_SUCCESS")) {
return "success";
} else {
return "error";
}
} else { //验签不通过
LOG.error("验签失败");
return "failure";
}
} catch (AlipayApiException e) {
LOG.error("验签失败:{}", e.getMessage());
return "failure";
}
}
}
调用类
package com.hyt.mall.pay.web.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hyt.mall.pay.web.service.impl.alipay.AlipayServiceImpl;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.hyt.mall.pay.web.config.WxpayConfig;
import com.hyt.mall.pay.web.req.OrderQueryReq;
import com.hyt.mall.pay.web.req.OrderRefundReq;
import com.hyt.mall.pay.web.req.OrderPayReq;
import com.hyt.mall.pay.web.req.TransferDetailReq;
import com.hyt.mall.pay.web.service.IPayService;
import com.hyt.mall.pay.web.service.IUrlService;
import com.hyt.mall.pay.web.service.impl.wechat.WechatAppServiceImpl;
import com.hyt.mall.pay.web.service.impl.wechat.WechatMiniServiceImpl;
import com.hyt.mall.pay.web.util.AesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
-
@author zww
-
@Description:
-
@date 2023/3/3 14:08
*/
@Service
public class PayServiceImpl implements IPayService {private static final Logger LOG = LoggerFactory.getLogger(PayServiceImpl.class);
@Resource
private WechatMiniServiceImpl wechatMiniService;
@Resource
private WechatAppServiceImpl wechatAppService;
@Resource
private AlipayServiceImpl alipayService;
@Resource
private IUrlService urlService;private RSAAutoCertificateConfig config;
@Autowired
public void setConfig(){// 检查文件是否存在 防止本地调试时,项目启动异常File file = new File(WxpayConfig.privateKeyPath);if (!file.exists()) {LOG.error("\033[31m警告:未找到微信支付私钥文件,微信支付功能将被禁用\033[0m");return;}config = new RSAAutoCertificateConfig.Builder().merchantId(WxpayConfig.mchId).privateKeyFromPath(WxpayConfig.privateKeyPath).merchantSerialNumber(WxpayConfig.mchSerialNo).apiV3Key(WxpayConfig.apiV3Key).build();
}
@Override
public String pay(OrderPayReq param){
switch (param.getPayType()) {
case 1:
return wechatMiniService.pay(param,config);
case 2:
return wechatAppService.pay(param,config);
case 3:
return alipayService.pay(param);
default:
return null;
}
}@Override
public String query(OrderQueryReq param) {
switch (param.getPayType()) {
case 1:
return wechatMiniService.query(param,config);
case 2:
return wechatAppService.query(param,config);
case 3:
return alipayService.query(param);
default:
return null;
}
}@Override
public String refund(OrderRefundReq param) {
switch (param.getPayType()) {
case 1:
return wechatMiniService.refund(param,config);
case 2:
return wechatAppService.refund(param,config);
case 3:
return alipayService.refund(param);
default:
return null;
}
}@Override
public String refundQuery(Map<String, Object> param) {
switch (param.get("payType").toString()) {
case "1":
return wechatMiniService.refundQuery(param, config);
case "2":
return wechatAppService.refundQuery(param, config);
case "3":
return alipayService.refundQuery(param);
default:
return null;
}
}@Override
public String close(OrderQueryReq param) {
switch (param.getPayType()) {
case 1:
return wechatMiniService.close(param, config);
case 2:
return wechatAppService.close(param, config);
case 3:
return alipayService.close(param);
default:
return null;
}
}@Override
public String notify(HttpServletRequest request, HttpServletResponse response) {
return null;
}@Override
public Map<String,String> wxNotify(JSONObject jsonObject) {
//应答体
Map<String,String> map = new HashMap<>();
try {
String key = WxpayConfig.apiV3Key;
LOG.info("支付回调结果:{}", JSON.toJSONString(jsonObject));
String paymentId = jsonObject.getString("id");
JSONObject resourceObj = JSONObject.parseObject(JSON.toJSONString(jsonObject.get("resource")),JSONObject.class);
String associated_data = resourceObj.getString("associated_data");
String ciphertext = resourceObj.getString("ciphertext");
String nonce = resourceObj.getString("nonce");String decryptData = new AesUtil(key.getBytes(StandardCharsets.UTF_8)).decryptToString(associated_data.getBytes(StandardCharsets.UTF_8),nonce.getBytes(StandardCharsets.UTF_8), ciphertext);//验签成功JSONObject obj = JSONObject.parseObject(decryptData, JSONObject.class);if (obj.get("trade_state").toString().equals("SUCCESS")) {String orderNo = obj.get("out_trade_no").toString();//String tradeType = obj.get("trade_type").toString();int result = urlService.updateOrderStatus(orderNo, 1, obj.get("transaction_id").toString());if (result > 0) {map.put("code","SUCCESS");map.put("message","成功");} else {LOG.info("单号:{}, 异常:{}", obj.get("out_trade_no").toString(), "修改订单状态失败!");map.put("code","FAIL");map.put("message","失败");}} else {LOG.info("单号:{}, 交易状态:{},异常:{}", obj.get("out_trade_no").toString(), obj.get("trade_state").toString(), "微信支付失败!");map.put("code","FAIL");map.put("message","失败");}return map;} catch (Exception e){LOG.info("params{}, 异常:", jsonObject.toJSONString(), e);map.put("code","FAIL");map.put("message","失败");return map;}
}
@Override
public Map<String,String> wxRefundNotify(JSONObject jsonObject) {
//应答体
Map<String,String> map = new HashMap<>();
try {
String key = WxpayConfig.apiV3Key;
JSONObject resourceObj = JSONObject.parseObject(JSON.toJSONString(jsonObject.get("resource")),JSONObject.class);
String associated_data = resourceObj.getString("associated_data");
String ciphertext = resourceObj.getString("ciphertext");
String nonce = resourceObj.getString("nonce");String decryptData = new AesUtil(key.getBytes(StandardCharsets.UTF_8)).decryptToString(associated_data.getBytes(StandardCharsets.UTF_8),nonce.getBytes(StandardCharsets.UTF_8), ciphertext);//验签成功JSONObject obj = JSONObject.parseObject(decryptData, JSONObject.class);switch (obj.get("refund_status").toString()) {case "SUCCESS":JSONObject amountObj = JSONObject.parseObject(JSON.toJSONString(obj.get("amount")), JSONObject.class);Integer refundAmount = (Integer) amountObj.get("payer_refund");BigDecimal amount = BigDecimal.valueOf(refundAmount.floatValue()/100);int result = urlService.updateOrderRefundStatus(obj.get("out_trade_no").toString(), amount.setScale(2, BigDecimal.ROUND_HALF_UP));LOG.info("result:{}", result);if (result > 0) {map.put("code","SUCCESS");map.put("message","成功");} else {LOG.info("单号:{}, 异常:{}", obj.get("out_trade_no").toString(), "退款修改订单状态失败!");map.put("code", "FAIL");map.put("message", "退款关闭!");}return map;case "CLOSED":LOG.info("单号:{}, 异常:{}", obj.get("out_trade_no").toString(), "退款关闭!");map.put("code", "FAIL");map.put("message", "退款关闭!");break;case "ABNORMAL":LOG.info("单号:{}, 异常:{}", obj.get("out_trade_no").toString(), "退款异常,用户的卡作废或者冻结了!");map.put("code", "FAIL");map.put("message", "失败!退款异常,用户的卡作废或者冻结了!");break;default:map.put("code", "FAIL");map.put("message", "失败");break;}return map;}catch (Exception e){LOG.info("params{}, 异常:", jsonObject.toJSONString(), e);map.put("code","FAIL");map.put("message","失败");return map;}
}
@Override
public String initiateBatchTransfer(TransferDetailReq param) {
if (param.getTransferAmount().compareTo(BigDecimal.ZERO) <= 0) {
LOG.info("initiateBatchTransfer:{}", param.toString());
return null;
}
// String result = wechatMiniService.initiateBatchTransfer(param, config);
// JSONObject json = JSONObject.parseObject(result, JSONObject.class);
return wechatMiniService.initiateBatchTransfer(param, config);
}@Override
public String initiateBatchTransferList(Listlist) {
if (ObjectUtils.isEmpty(list) || list.size() < 1) {
return null;
}
return wechatMiniService.initiateBatchTransferList(list, config);
}
}