本文目录导读:

我来为你提供一个完整的支付宝支付Java集成案例,包含当面付(扫码支付)和手机网站支付两种常见场景。
环境准备
1 Maven依赖
<dependencies>
<!-- 支付宝SDK -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.38.72.ALL</version>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.40</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
</dependencies>
2 配置文件 (application.yml)
alipay: # 应用ID app-id: your_app_id # 商户私钥 app-private-key: your_app_private_key # 支付宝公钥 alipay-public-key: your_alipay_public_key # 网关地址 gateway-url: https://openapi.alipay.com/gateway.do # 签名类型 sign-type: RSA2 # 编码格式 charset: UTF-8 # 格式 format: json # 异步通知地址 notify-url: http://your-domain.com/alipay/notify # 同步返回地址 return-url: http://your-domain.com/alipay/return
核心配置类
package com.example.alipay.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String gatewayUrl;
private String signType = "RSA2";
private String charset = "UTF-8";
private String format = "json";
private String notifyUrl;
private String returnUrl;
// getters and setters...
@Bean
public AlipayClient alipayClient() {
return new DefaultAlipayClient(
gatewayUrl,
appId,
appPrivateKey,
format,
charset,
alipayPublicKey,
signType
);
}
}
支付服务实现
1 支付服务接口
package com.example.alipay.service;
import com.example.alipay.dto.AlipayOrderDTO;
import com.example.alipay.dto.AlipayQueryDTO;
import com.example.alipay.dto.AlipayRefundDTO;
import java.util.Map;
public interface AlipayService {
/**
* 当面付(扫码支付)
*/
String qrcodePay(AlipayOrderDTO orderDTO) throws Exception;
/**
* 手机网站支付
*/
String webPay(AlipayOrderDTO orderDTO) throws Exception;
/**
* 查询订单
*/
AlipayQueryDTO queryOrder(String outTradeNo) throws Exception;
/**
* 退款
*/
boolean refund(AlipayRefundDTO refundDTO) throws Exception;
/**
* 处理异步通知
*/
String handleNotify(Map<String, String> params) throws Exception;
}
2 支付服务实现类
package com.example.alipay.service.impl;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.example.alipay.dto.AlipayOrderDTO;
import com.example.alipay.dto.AlipayQueryDTO;
import com.example.alipay.dto.AlipayRefundDTO;
import com.example.alipay.service.AlipayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;
@Slf4j
@Service
public class AlipayServiceImpl implements AlipayService {
@Autowired
private AlipayClient alipayClient;
@Autowired
private AlipayConfig alipayConfig;
@Override
public String qrcodePay(AlipayOrderDTO orderDTO) throws Exception {
// 构建请求
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setNotifyUrl(alipayConfig.getNotifyUrl());
// 构建业务参数
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(orderDTO.getOutTradeNo());
model.setTotalAmount(orderDTO.getTotalAmount().toString());
model.setSubject(orderDTO.getSubject());
model.setBody(orderDTO.getBody());
request.setBizModel(model);
// 发起请求
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
log.info("支付宝当面付成功,订单号:{},二维码链接:{}",
orderDTO.getOutTradeNo(), response.getQrCode());
return response.getQrCode();
} else {
log.error("支付宝当面付失败,错误码:{},错误信息:{}",
response.getCode(), response.getMsg());
throw new RuntimeException("支付失败:" + response.getMsg());
}
}
@Override
public String webPay(AlipayOrderDTO orderDTO) throws Exception {
// 构建请求
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl(alipayConfig.getNotifyUrl());
request.setReturnUrl(alipayConfig.getReturnUrl());
// 构建业务参数
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(orderDTO.getOutTradeNo());
model.setTotalAmount(orderDTO.getTotalAmount().toString());
model.setSubject(orderDTO.getSubject());
model.setBody(orderDTO.getBody());
model.setProductCode("QUICK_WAP_WAY");
request.setBizModel(model);
// 生成支付表单
return alipayClient.pageExecute(request).getBody();
}
@Override
public AlipayQueryDTO queryOrder(String outTradeNo) throws Exception {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(outTradeNo);
request.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(request);
AlipayQueryDTO queryDTO = new AlipayQueryDTO();
if (response.isSuccess()) {
queryDTO.setTradeNo(response.getTradeNo());
queryDTO.setOutTradeNo(response.getOutTradeNo());
queryDTO.setTradeStatus(response.getTradeStatus());
queryDTO.setTotalAmount(new BigDecimal(response.getTotalAmount()));
queryDTO.setReceiptAmount(new BigDecimal(response.getReceiptAmount()));
queryDTO.setBuyerLogonId(response.getBuyerLogonId());
queryDTO.setGmtPayment(response.getGmtPayment());
}
return queryDTO;
}
@Override
public boolean refund(AlipayRefundDTO refundDTO) throws Exception {
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(refundDTO.getOutTradeNo());
model.setRefundAmount(refundDTO.getRefundAmount().toString());
model.setRefundReason(refundDTO.getRefundReason());
request.setBizModel(model);
AlipayTradeRefundResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
log.info("退款成功,订单号:{},退款金额:{}",
refundDTO.getOutTradeNo(), refundDTO.getRefundAmount());
return true;
} else {
log.error("退款失败,错误码:{},错误信息:{}",
response.getCode(), response.getMsg());
return false;
}
}
@Override
public String handleNotify(Map<String, String> params) throws Exception {
// 验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(
params,
alipayConfig.getAlipayPublicKey(),
alipayConfig.getCharset(),
alipayConfig.getSignType()
);
if (!signVerified) {
log.error("支付宝异步通知签名验证失败");
return "failure";
}
// 获取通知参数
String outTradeNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
String tradeStatus = params.get("trade_status");
String totalAmount = params.get("total_amount");
String gmtPayment = params.get("gmt_payment");
log.info("支付宝异步通知,订单号:{},交易状态:{}", outTradeNo, tradeStatus);
// 处理业务逻辑(更新订单状态等)
if ("TRADE_SUCCESS".equals(tradeStatus)) {
// 支付成功,更新订单状态
// 注意:需要判断处理过的通知不做重复处理
boolean success = processPaymentSuccess(outTradeNo, tradeNo, totalAmount, gmtPayment);
return success ? "success" : "failure";
}
return "success";
}
private boolean processPaymentSuccess(String outTradeNo, String tradeNo,
String totalAmount, String gmtPayment) {
// 实现具体的业务逻辑,如更新数据库订单状态
log.info("处理支付成功回调,订单号:{},支付宝交易号:{}", outTradeNo, tradeNo);
return true;
}
}
DTO对象
1 订单DTO
package com.example.alipay.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class AlipayOrderDTO {
private String outTradeNo; // 商户订单号
private BigDecimal totalAmount; // 支付金额
private String subject; // 订单标题
private String body; // 订单描述
private Integer timeoutExpress = 30; // 超时时间(分钟)
}
2 查询DTO
package com.example.alipay.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class AlipayQueryDTO {
private String tradeNo; // 支付宝交易号
private String outTradeNo; // 商户订单号
private String tradeStatus; // 交易状态
private BigDecimal totalAmount; // 交易金额
private BigDecimal receiptAmount; // 实收金额
private String buyerLogonId; // 买家支付宝账号
private String gmtPayment; // 支付时间
}
3 退款DTO
package com.example.alipay.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class AlipayRefundDTO {
private String outTradeNo; // 商户订单号
private BigDecimal refundAmount; // 退款金额
private String refundReason; // 退款原因
}
控制层
package com.example.alipay.controller;
import com.example.alipay.dto.AlipayOrderDTO;
import com.example.alipay.dto.AlipayQueryDTO;
import com.example.alipay.dto.AlipayRefundDTO;
import com.example.alipay.service.AlipayService;
import com.example.alipay.util.OrderNumberGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/alipay")
public class AlipayController {
@Autowired
private AlipayService alipayService;
/**
* 发起当面付(扫码支付)
*/
@PostMapping("/qrcodePay")
public Map<String, Object> qrcodePay(@RequestBody AlipayOrderDTO orderDTO) {
Map<String, Object> result = new HashMap<>();
try {
// 生成订单号
orderDTO.setOutTradeNo(OrderNumberGenerator.generate());
String qrCode = alipayService.qrcodePay(orderDTO);
result.put("code", 200);
result.put("message", "success");
result.put("data", qrCode);
result.put("outTradeNo", orderDTO.getOutTradeNo());
} catch (Exception e) {
log.error("发起支付宝支付失败", e);
result.put("code", 500);
result.put("message", "支付失败:" + e.getMessage());
}
return result;
}
/**
* 发起手机网站支付
*/
@PostMapping("/webPay")
public Map<String, Object> webPay(@RequestBody AlipayOrderDTO orderDTO) {
Map<String, Object> result = new HashMap<>();
try {
orderDTO.setOutTradeNo(OrderNumberGenerator.generate());
String form = alipayService.webPay(orderDTO);
result.put("code", 200);
result.put("message", "success");
result.put("data", form);
} catch (Exception e) {
log.error("发起手机网站支付失败", e);
result.put("code", 500);
result.put("message", "支付失败:" + e.getMessage());
}
return result;
}
/**
* 查询订单
*/
@GetMapping("/query/{outTradeNo}")
public Map<String, Object> queryOrder(@PathVariable String outTradeNo) {
Map<String, Object> result = new HashMap<>();
try {
AlipayQueryDTO queryDTO = alipayService.queryOrder(outTradeNo);
result.put("code", 200);
result.put("message", "success");
result.put("data", queryDTO);
} catch (Exception e) {
log.error("查询订单失败", e);
result.put("code", 500);
result.put("message", "查询失败:" + e.getMessage());
}
return result;
}
/**
* 退款
*/
@PostMapping("/refund")
public Map<String, Object> refund(@RequestBody AlipayRefundDTO refundDTO) {
Map<String, Object> result = new HashMap<>();
try {
boolean success = alipayService.refund(refundDTO);
result.put("code", success ? 200 : 500);
result.put("message", success ? "退款成功" : "退款失败");
} catch (Exception e) {
log.error("退款失败", e);
result.put("code", 500);
result.put("message", "退款失败:" + e.getMessage());
}
return result;
}
/**
* 异步通知处理
*/
@PostMapping("/notify")
public String handleNotify(HttpServletRequest request) {
try {
// 获取支付宝POST过来的参数
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
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] + ",";
}
params.put(name, valueStr);
}
return alipayService.handleNotify(params);
} catch (Exception e) {
log.error("处理支付宝异步通知失败", e);
return "failure";
}
}
/**
* 同步返回处理
*/
@GetMapping("/return")
public String handleReturn(HttpServletRequest request) {
// 处理同步返回,通常只是展示成功页面
// 真正的业务逻辑应在异步通知中处理
return "支付成功,正在返回...";
}
}
工具类
1 订单号生成器
package com.example.alipay.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class OrderNumberGenerator {
private static int sequence = 0;
private static final Object lock = new Object();
/**
* 生成唯一订单号
*/
public static String generate() {
synchronized (lock) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String dateStr = sdf.format(new Date());
// 序列号,确保同一毫秒内不会重复
if (sequence >= 1000) {
sequence = 0;
}
sequence++;
return dateStr + String.format("%03d", sequence) + getRandomChar(3);
}
}
/**
* 生成随机字符
*/
private static String getRandomChar(int length) {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int index = (int) (Math.random() * chars.length());
sb.append(chars.charAt(index));
}
return sb.toString();
}
}
2 金额工具类
package com.example.alipay.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class AmountUtil {
/**
* 元转分
*/
public static long yuanToFen(BigDecimal yuan) {
return yuan.multiply(new BigDecimal(100))
.setScale(0, RoundingMode.HALF_UP)
.longValue();
}
/**
* 分转元
*/
public static BigDecimal fenToYuan(long fen) {
return new BigDecimal(fen)
.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
}
/**
* 格式化金额
*/
public static String format(BigDecimal amount) {
return amount.setScale(2, RoundingMode.HALF_UP).toString();
}
}
集成测试示例
package com.example.alipay;
import com.example.alipay.dto.AlipayOrderDTO;
import com.example.alipay.service.AlipayService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
@Slf4j
@SpringBootTest
public class AlipayPaymentTest {
@Autowired
private AlipayService alipayService;
@Test
public void testQrcodePay() throws Exception {
// 准备订单数据
AlipayOrderDTO orderDTO = new AlipayOrderDTO();
orderDTO.setOutTradeNo("ORDER" + System.currentTimeMillis());
orderDTO.setTotalAmount(new BigDecimal("0.01"));
orderDTO.setSubject("测试商品");
orderDTO.setBody("测试商品描述");
// 发起支付
String qrCode = alipayService.qrcodePay(orderDTO);
log.info("生成的二维码链接:{}", qrCode);
System.out.println("请使用支付宝扫描以下二维码进行支付:");
System.out.println(qrCode);
}
@Test
public void testQueryOrder() throws Exception {
String outTradeNo = "ORDER1234567890";
com.example.alipay.dto.AlipayQueryDTO queryDTO = alipayService.queryOrder(outTradeNo);
log.info("订单信息:{}", queryDTO);
}
}
注意事项
1 配置文件示例
# 支付宝配置 alipay.app-id=2021000118600001 alipay.app-private-key=MIIEvQIBADANB... (完整RSA私钥) alipay.alipay-public-key=MIIBIjANBg... (完整RSA公钥) alipay.gateway-url=https://openapi.alipay.com/gateway.do alipay.sign-type=RSA2 alipay.charset=UTF-8 alipay.format=json alipay.notify-url=http://your-domain.com/alipay/notify alipay.return-url=http://your-domain.com/alipay/return
2 重要提示
- 密钥安全:私钥不要在代码中硬编码,建议使用配置中心或环境变量
- 异步通知:一定要验证签名,并确保回调幂等性
- 订单号唯一性:确保生成的订单号全局唯一
- 金额精度:使用BigDecimal处理金额,避免浮点数精度问题
- 日志记录:记录所有关键操作的日志,便于排查问题
3 常见问题处理
// 签名失败处理
public static boolean verifySign(Map<String, String> params, String alipayPublicKey) {
try {
return AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
} catch (Exception e) {
log.error("签名验证异常", e);
return false;
}
}
这个案例涵盖了支付宝支付的主要功能,可根据实际需求进行调整和扩展,建议在沙箱环境中测试通过后再切换到生产环境。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播