前提:注册支付宝开放平台 开放平台
并且登录到沙箱控制台 登录 - 支付宝
1.准备工作做完,加pom依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.110.ALL</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.0</version>
</dependency>
2.配置 将以下配置写入nacos
alipay:
#APPID
appId: 支付宝账号ID
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
#应用私钥
appPrivateKey: 这里写账号里的私钥
#支付宝公钥
alipayPublicKey: 支付宝公钥
#回调接口 (使用内网穿透:https://natapp.cn/)
returnUrl: https://www.baidu.com/s?ie=UTF-8&wd=%E5%8C%97%E4%BA%AC%E6%97%B6%E9%97%B4
# 支付通知的回调地址,支付宝会在支付完成后通知这个地址
notifyUrl: http://j97sy7.natappfree.cc/priceSum/notify
# 参数返回格式,只支持JSON
format: JSON
# 请求使用的编码格式
charset: UTF-8
# 生成签名字符串所使用的签名算法类型
signType: RSA2
注:支付宝公钥 分为两种,一种 支付宝公钥 一种应用公钥,这里一定要用支付宝公钥,不要写错了!!!
如图所示:
3.配置工具类
package com.shopgoods.order.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig {
/**
* 支付宝网关
*/
private String gatewayUrl;
/**
* 应用ID
*/
private String appId;
/**
* 应用私钥
*/
private String appPrivateKey;
/**
* 支付宝公钥
*/
private String alipayPublicKey;
/**
* 用户确认支付后,支付宝调用的页面返回路径
* 开发环境为:http://localhost:8060/#/pages/money/paySuccess
*/
private String returnUrl;
/**
* 支付成功后,支付宝服务器主动通知商户服务器里的异步通知回调(需要公网能访问)
* 开发环境为:http://localhost:8085/alipay/notify
*/
private String notifyUrl;
/**
* 参数返回格式,只支持JSON
*/
private String format;
/**
* 请求使用的编码格式
*/
private String charset;
/**
* 生成签名字符串所使用的签名算法类型
*/
private String signType;
}
4.当Spring容器启动时,它会自动调用alipayClient方法,并将结果作为bean存储在Spring的IoC(控制反转)容器中,这样在整个应用程序中都可以方便地注入和使用这个AlipayClient实例来进行支付宝相关的操作
package com.shopgoods.order.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AlipayClientConfig {
@Bean
public AlipayClient alipayClient(AlipayConfig config){
return new DefaultAlipayClient(config.getGatewayUrl(),config.getAppId(),config.getAppPrivateKey(), config.getFormat(),config.getCharset(),config.getAlipayPublicKey(),config.getSignType());
}
}
创建Service
package com.shopgoods.order.service;
import com.shopgoods.order.config.AlipayConfig;
import com.shopgoods.order.domain.AliPayParam;
import com.shopgoods.order.domain.PricesSum;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @ClassName: PriceSumService
* @Description: TODO
* @Author: qh
* @Date: 2024/11/22 18:34
*/
public interface PriceSumService {
String webPay(AliPayParam aliPayParam);
/**
* 支付宝异步回调处理
*/
String notify(Map<String, String> params);
}
创建ServiceImpl
package com.shopgoods.order.service.impl;
import com.alibaba.csp.sentinel.util.StringUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.shopgoods.order.config.AlipayConfig;
import com.shopgoods.order.domain.AliPayParam;
import com.shopgoods.order.mapper.OrderMapper;
import com.shopgoods.order.service.IOrderService;
import com.shopgoods.order.service.PriceSumService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import static org.bouncycastle.asn1.x500.style.RFC4519Style.cn;
/**
* @ClassName: PriceSumServiceImpl
* @Description: TODO
* @Author: qh
* @Date: 2024/11/22 18:35
*/
@Service
@Log4j2
public class PriceSumServiceImpl implements PriceSumService {
@Autowired
private AlipayClient alipayClient;
@Autowired
private OrderMapper orderMapper;
@Autowired
private IOrderService orderService;
@Autowired
private AlipayConfig alipayConfig;
@Override
public String webPay(AliPayParam aliPayParam) {
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest ();
if(StrUtil.isNotEmpty(alipayConfig.getNotifyUrl())){
//异步接收地址,公网可访问
request.setNotifyUrl(alipayConfig.getNotifyUrl());
}
if(StrUtil.isNotEmpty(alipayConfig.getReturnUrl())){
//同步跳转地址
request.setReturnUrl(alipayConfig.getReturnUrl());
}
//******必传参数******
JSONObject bizContent = new JSONObject();
//商户订单号,商家自定义,保持唯一性
bizContent.put("out_trade_no", aliPayParam.getOutTradeNo());
//支付金额,最小值0.01元
bizContent.put("total_amount", aliPayParam.getTotalAmount());
//订单标题,不可使用特殊符号
bizContent.put("subject", aliPayParam.getSubject());
//手机网站支付默认传值FAST_INSTANT_TRADE_PAY
bizContent.put("product_code", "QUICK_WAP_WAY");
request.setBizContent(bizContent.toString());
String formHtml = null;
try {
formHtml = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return formHtml;
}
@Override
public String notify(Map<String, String> params) {
String result = "failure";
boolean signVerified = false;
try {
//调用SDK验证签名
signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
} catch (AlipayApiException e) {
log.error("支付回调签名校验异常!",e);
e.printStackTrace();
}
if (signVerified) {
String tradeStatus = params.get("trade_status");
if("TRADE_SUCCESS".equals(tradeStatus)){
result = "success";
log.info("notify方法被调用了,tradeStatus:{}",tradeStatus);
String outTradeNo = params.get("out_trade_no");
// portalOrderService.paySuccessByOrderSn(outTradeNo,1);
//支付成功修改状态
orderService.updatePaySuccessByOrderSn(outTradeNo,3);
}else{
log.warn("订单未支付成功,trade_status:{}",tradeStatus);
}
} else {
log.warn("支付回调签名校验失败!");
}
return result;
}
6.回调之前必须提前配置好内网穿透
先下载natapp
内网穿透链接:NATAPP -
购买一个免费隧道就可以了
将nacos回调地址更改为以上的地址