pom依賴:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.8.73.ALL</version>
</dependency>
application.yml配置:
ali-pay:
app-id:
private-key:
app-cert-path: classpath:cert/appCertPublicKey_xxx.crt
alipay-cert-path: classpath:cert/alipayCertPublicKey_RSA2.crt
alipay-root-cert-path: classpath:cert/alipayRootCert.crt
notify-url: http://xxx.xxx.com:8080/pay/alipay/notify
讀取配置信息,初始化配置,兩個文件:
@Configuration
@ConfigurationProperties(prefix = "ali-pay")
@Data
public class AliPayProperties {
private String appId;
private String privateKey;
private String notifyUrl;
private String appCertPath;
private String alipayCertPath;
private String alipayRootCertPath;
}
@Configuration
public class AliPayConfig {
private final AliPayProperties properties;
public AliPayConfig(AliPayProperties properties) {
this.properties = properties;
}
@Bean
public AlipayClient alipayClient() throws AlipayApiException, FileNotFoundException {
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
certAlipayRequest.setAppId(properties.getAppId());
certAlipayRequest.setPrivateKey(properties.getPrivateKey());
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset(AlipayConstants.CHARSET_UTF8);
certAlipayRequest.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
certAlipayRequest.setCertPath(ResourceUtils.getFile(properties.getAppCertPath()).getAbsolutePath());
certAlipayRequest.setAlipayPublicCertPath(ResourceUtils.getFile(properties.getAlipayCertPath()).getAbsolutePath());
certAlipayRequest.setRootCertPath(ResourceUtils.getFile(properties.getAlipayRootCertPath()).getAbsolutePath());
return new DefaultAlipayClient(certAlipayRequest);
}
}
支付寶支付/退款/查詢:
/**
* 支付寶預支付
* @param body
* @return
*/
public String aliPrepay(PayRequest body) {
// TODO 先保存支付請求歷史記錄
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody(body.getBody());
model.setSubject(body.getSubject());
model.setOutTradeNo(body.getPaySn());
model.setTimeoutExpress("30m"); // 非必填
model.setTotalAmount(body.getTotalFee().toString());
model.setPassbackParams(body.getAttach()); // 非必填
request.setBizModel(model);
request.setNotifyUrl(aliPayProperties.getNotifyUrl());
try {
//這裏和普通的接口調用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
//就是orderString 可以直接給客戶端請求,無需再做處理。
String returnBody = response.getBody();
return returnBody;
} catch (AlipayApiException e) {
e.printStackTrace();
log.error("aliPrepay", e);
}
return null;
}
/**
* 支付寶通知回調處理
* @param request
* @return
*/
public String aliPayNotify(HttpServletRequest request) {
Map<String, String[]> requestParams = request.getParameterMap();
Map<String, String> params = new HashMap<>(requestParams.size());
for (String key : requestParams.keySet()) {
String[] values = requestParams.get(key);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(key, valueStr);
}
try {
// alipaypublickey是支付寶的公鑰
boolean signVerified = AlipaySignature.rsaCertCheckV1(params,
ResourceUtils.getFile(aliPayProperties.getAlipayCertPath()).getAbsolutePath(),
AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
if (!signVerified) {
log.info("支付寶支付-通知回調簽名認證失敗");
return "failure";
}
// 按照支付結果異步通知中的描述,對支付結果中的業務內容進行1\2\3\4二次校驗,
/* 1、商戶需要驗證該通知數據中的out_trade_no是否爲商戶系統中創建的訂單號,
* 2、判斷total_amount是否確實爲該訂單的實際金額(即商戶訂單創建時的金額),
* 3、校驗通知中的seller_id(或者seller_email)是否爲out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email),可根據實際情況省略
* 4、驗證app_id是否爲該商戶本身。上述1、2、3、4有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略。
* 在上述驗證通過後商戶必須根據支付寶不同類型的業務通知,正確的進行不同的業務處理,並且過濾重複的通知結果數據。
* 在支付寶的業務通知中,只有交易通知狀態爲TRADE_SUCCESS或TRADE_FINISHED時,支付寶纔會認定爲買家付款成功。*/
// 1,2,3,省略;4、驗證app_id是否爲該商戶本身。
if (!params.get("app_id").equals(aliPayProperties.getAppId())) {
throw new AlipayApiException("app_id不一致");
}
String tradeStatus = (String) params.get("tradeStatus");
// 支付成功
if (tradeStatus.equals(AliPayTradeStatus.TRADE_SUCCESS.name())
|| tradeStatus.equals(AliPayTradeStatus.TRADE_FINISHED.name())) {
// 支付成功業務處理
} else {
// 支付失敗
}
return "success";
} catch (AlipayApiException e) {
log.error("支付寶支付-失敗", e);
return "failure";
} catch (FileNotFoundException e) {
log.error("支付寶支付-公鑰文件不存在", e);
return "failure";
}
}
/**
* 支付寶支付訂單查詢
* @param tradeNo 支付寶訂單號
* @param paySn 本地支付流水號
* @return
*/
public String aliOrderQuery(String tradeNo, String paySn) {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setTradeNo(tradeNo);
model.setOutTradeNo(paySn);
request.setBizModel(model);
AlipayTradeQueryResponse response;
try {
response = alipayClient.execute(request);
if (!"10000".equals(response.getCode())) {
throw new AlipayApiException("支付寶支付-查詢失敗!");
}
} catch (AlipayApiException e) {
log.error("支付寶支付-查詢失敗", e);
// 失敗
}
if (!"TRADE_SUCCESS".equals(response.getTradeStatus())) {
// 失敗
}
// 成功
response.getTradeStatus();
response.getTradeNo();
response.getOutTradeNo();
response.getTotalAmount();
response.getSendPayDate();
}
/**
* 支付寶退款
* @param body
* @return
*/
private String aliRefund(RefundRequest body) {
AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setOutTradeNo(body.getPaySerial());
model.setRefundAmount(body.getPayAmount().toString());
model.setRefundReason("商品退款");
refundRequest.setBizModel(model);
try {
AlipayTradeRefundResponse response = alipayClient.certificateExecute(refundRequest);
if (response.isSuccess() && response.getFundChange().equalsIgnoreCase("Y")) {
// 成功
} else {
// 失敗
}
} catch (AlipayApiException e) {
e.printStackTrace();
log.error(" - aliRefund - ", e);
}
}