对接支付-Alipay 沙箱支付
1.注册支付宝开放平台账号
访问 支付宝|开放平台 地址:https://open.alipay.com/develop/manage,注册开发者账号并创建应用。
2.获取沙箱环境信息
在开放平台控制台进入「沙箱环境」,获取:
- 应用 ID(AppID)
- 商户私钥和支付宝公钥(需使用 密钥生成工具(密钥工具下载:https://opendocs.alipay.com/common/02kipk) 生成)
- 沙箱测试账号
3.添加支付宝 SDK 依赖(Maven)
<!-- 支付宝沙箱支付对接文档:https://opendocs.alipay.com/common/02kkv7 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.38.157.ALL</version>
</dependency>
4.创建配置类存储支付宝相关参数
https://opendocs.alipay.com/open/00dn74
@Data
@ConfigurationProperties(prefix = "alipay", ignoreInvalidFields = true)
public class AliPayConfigProperties {
//获取地址;https://open.alipay.com/develop/sandbox/app
private String app_id="";
//「沙箱环境」商户私钥,你的PKCS8格式RSA2私钥
private String app_private_key="";
// 「沙箱环境」支付宝公钥
private String alipay_public_key="";
// 「沙箱环境」服务器异步通知页面路径
private String notify_url;
// 「沙箱环境」页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
private String return_url;
// 「沙箱环境」支付宝网关(固定)https://openapi-sandbox.dl.alipaydev.com/gateway.do
private String serverUrl;
// 签名方式
private String sign_type = "RSA2";
// 字符编码格式
private String charset = "utf-8";
// 传输格式
private String format = "json";
}
5.创建AlipayClient实例
@Configuration
@EnableConfigurationProperties(AliPayConfigProperties.class)
public class AliPayConfig {
@Bean("alipayClient")
public AlipayClient alipayClient(AliPayConfigProperties properties){
return new DefaultAlipayClient(
properties.getServerUrl(),
properties.getApp_id(),
properties.getApp_private_key(),
properties.getFormat(),
properties.getCharset(),
properties.getAlipay_public_key(),
properties.getSign_type()
);
}
}
6.统一下单接口实现
private PayOrder doPrepayOrder(String productId, String productName, String orderId, BigDecimal totalAmount) throws AlipayApiException {
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(notifyUrl);
request.setReturnUrl(returnUrl);
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderId);//设置商户订单号
bizContent.put("total_amount", totalAmount.toString());//设置订单总金额
bizContent.put("subject", productName);//设置订单标题
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");//设置产品码 FAST_INSTANT_TRADE_PAY 电脑网站支付(PC 端支付页面)
request.setBizContent(bizContent.toString());
String form = alipayClient.pageExecute(request).getBody();
log.info("测试结果\r\n\n把我复制到 index.html ->:{}", form);
PayOrder payOrder = new PayOrder();
payOrder.setOrderId(orderId);
payOrder.setPayUrl(form);
payOrder.setStatus(Constants.OrderStatusEnum.PAY_WAIT.getCode());
orderDao.updateOrderPayInfo(payOrder);
return payOrder;
}
7.异步通知处理
@RequestMapping(value = "alipay_notify_url", method = RequestMethod.POST)
public String payNotify(HttpServletRequest request) throws AlipayApiException {
log.info("支付回调,消息接收 {}", request.getParameter("trade_status"));
if (!request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
return "false";
}
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
log.info("参数:{}——{}",name,request.getParameter(name));
params.put(name, request.getParameter(name));
}
String sign = params.get("sign"); // 从参数中获取签名
String content = AlipaySignature.getSignCheckContentV1(params); // 生成待签名字符串
log.info("待验签内容:{} ",content);
log.info("签名:{} ", sign);
boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alipayPublicKey, "UTF-8"); // 验证签名
// 支付宝验签
if (!checkSignature) {
return "false";
}
// 验签通过
log.info("支付回调,交易名称: {}", params.get("subject"));
log.info("支付回调,交易状态: {}", params.get("trade_status"));
log.info("支付回调,支付宝交易凭证号: {}", params.get("trade_no"));
log.info("支付回调,商户订单号: {}", params.get("out_trade_no"));
log.info("支付回调,交易金额: {}", params.get("total_amount"));
log.info("支付回调,买家在支付宝唯一id: {}", params.get("buyer_id"));
log.info("支付回调,买家付款时间: {}", params.get("gmt_payment"));
log.info("支付回调,买家付款金额: {}", params.get("buyer_pay_amount"));
log.info("支付回调,支付回调,更新订单 {}", params.get("out_trade_no"));
return "success";
}
8.查询订单是否已支付(处理调单补偿)
List<String> orderIds = orderService.queryNoPayNotifyOrder();
if (null == orderIds || orderIds.isEmpty()) {return;}
for (String orderId : orderIds) {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();
bizModel.setOutTradeNo(orderId);
request.setBizModel(bizModel);
AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(request);
String trade_status = alipayTradeQueryResponse.getTradeStatus();
// 判断状态码
if ("TRADE_SUCCESS".equals(trade_status)) {
orderService.changeOrderPaySuccess(orderId);
}
}