添加支付宝支付回调解析以及验签

This commit is contained in:
b2baccline
2021-01-26 15:21:14 +08:00
parent 1793087291
commit e52e59ddd8
7 changed files with 227 additions and 56 deletions

View File

@@ -8,6 +8,7 @@ import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePayModel; import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel; import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel; import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.request.AlipayTradeQueryRequest;
@@ -20,8 +21,8 @@ import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.hccake.starte.pay.ali.domain.AliPayQuery; import com.hccake.starte.pay.ali.domain.AliPayQuery;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.Map;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
/** /**
* api文档: https://opendocs.alipay.com/apis. * api文档: https://opendocs.alipay.com/apis.
@@ -353,6 +354,30 @@ public class AliPay {
return client.execute(request); return client.execute(request);
} }
/**
* v1 版本验签
* @param map 所有参数
* @return boolean
* @author lingting 2021-01-26 14:46
*/
public boolean checkSignV1(Map<String, String> map) throws AlipayApiException {
// 验签需要先移除 fund_bill_list 参数值中的 &quot; 否则会导致正确的签名验签失败
map.put("fund_bill_list", map.get("fund_bill_list").replaceAll("&quot;","\""));
return AlipaySignature.rsaCheckV1(map, alipayPublicKey, charset, signType);
}
/**
* v2 版本验签
* @param map 所有参数
* @return boolean
* @author lingting 2021-01-26 14:46
*/
public boolean checkSignV2(Map<String, String> map) throws AlipayApiException {
// 验签需要先移除 fund_bill_list 参数值中的 &quot; 否则会导致正确的签名验签失败
map.put("fund_bill_list", map.get("fund_bill_list").replaceAll("&quot;","\""));
return AlipaySignature.rsaCheckV2(map, alipayPublicKey, charset, signType);
}
/** /**
* 金额单位转换, 元 转为 分 * 金额单位转换, 元 转为 分
* @param amount 支付金额, 单位 元 * @param amount 支付金额, 单位 元

View File

@@ -0,0 +1,121 @@
package com.hccake.starte.pay.ali.domain;
import static com.hccake.ballcat.common.core.util.JacksonUtils.toJson;
import static com.hccake.ballcat.common.core.util.JacksonUtils.toObj;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.hccake.starte.pay.ali.enums.TradeStatus;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lingting 2021/1/26 13:31
*/
@NoArgsConstructor
@Data
public class AliPayCallback {
/**
* 解析回调参数
* @param callbackParams 所有回调参数
* @return com.hccake.starte.pay.ali.domain.AliPayCallback
* @author lingting 2021-01-26 14:39
*/
public static AliPayCallback of(Map<String, String> callbackParams) {
Map<String, Object> map = new HashMap<>(callbackParams);
String fundBillListStr = callbackParams.get("fund_bill_list").replaceAll("&quot;", "\"");
map.put("fund_bill_list", toObj(fundBillListStr, List.class));
// 覆盖原值
callbackParams.put("fund_bill_list", fundBillListStr);
return toObj(toJson(map), AliPayCallback.class);
}
@JsonProperty("gmt_create")
private String gmtCreate;
@JsonProperty("charset")
private String charset;
@JsonProperty("seller_email")
private String sellerEmail;
@JsonProperty("subject")
private String subject;
@JsonProperty("sign")
private String sign;
@JsonProperty("buyer_id")
private String buyerId;
@JsonProperty("invoice_amount")
private BigDecimal invoiceAmount;
@JsonProperty("notify_id")
private String notifyId;
@JsonProperty("fund_bill_list")
private List<FundBill> fundBillList;
@JsonProperty("notify_type")
private String notifyType;
@JsonProperty("trade_status")
private TradeStatus tradeStatus;
@JsonProperty("receipt_amount")
private BigDecimal receiptAmount;
@JsonProperty("app_id")
private String appId;
@JsonProperty("buyer_pay_amount")
private BigDecimal buyerPayAmount;
@JsonProperty("sign_type")
private String signType;
@JsonProperty("seller_id")
private String sellerId;
@JsonProperty("gmt_payment")
private String gmtPayment;
@JsonProperty("notify_time")
private String notifyTime;
@JsonProperty("version")
private String version;
@JsonProperty("out_trade_no")
private String outTradeNo;
@JsonProperty("total_amount")
private BigDecimal totalAmount;
@JsonProperty("trade_no")
private String tradeNo;
@JsonProperty("auth_app_id")
private String authAppId;
@JsonProperty("buyer_logon_id")
private String buyerLogonId;
@JsonProperty("point_amount")
private BigDecimal pointAmount;
@Data
public static class FundBill {
private BigDecimal amount;
private String fundChannel;
}
}

View File

@@ -4,6 +4,7 @@ import static com.hccake.starte.pay.ali.constants.AliPayConstant.CODE_SUCCESS;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alipay.api.response.AlipayTradeQueryResponse; import com.alipay.api.response.AlipayTradeQueryResponse;
import com.hccake.starte.pay.ali.enums.TradeStatus;
import java.math.BigDecimal; import java.math.BigDecimal;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@@ -30,11 +31,11 @@ public class AliPayQuery {
// 状态处理 // 状态处理
if (CODE_SUCCESS.equals(raw.getCode())) { if (CODE_SUCCESS.equals(raw.getCode())) {
// 成功 // 成功
query.setStatus(Status.of(raw.getTradeStatus())); query.setStatus(TradeStatus.of(raw.getTradeStatus()));
} }
// 异常 // 异常
else { else {
query.setStatus(Status.ERROR); query.setStatus(TradeStatus.ERROR);
} }
// 金额 // 金额
@@ -62,7 +63,7 @@ public class AliPayQuery {
/** /**
* 订单状态 * 订单状态
*/ */
private Status status; private TradeStatus status;
private String code; private String code;
@@ -101,49 +102,4 @@ public class AliPayQuery {
private String userType; private String userType;
/**
* 交易状态
*/
public enum Status {
/**
* 成功
*/
SUCCESS,
/**
* 未支付
*/
WAIT,
/**
* 未付款交易超时关闭,或支付完成后全额退款
*/
CLOSED,
/**
* 交易结束,不可退款
*/
FINISHED,
/**
* 异常. 具体信息查询 subCode和subMsg
*/
ERROR,
;
public static Status of(String status) {
switch (status) {
case "WAIT_BUYER_PAY":
return WAIT;
case "TRADE_CLOSED":
return CLOSED;
case "TRADE_SUCCESS":
return SUCCESS;
case "TRADE_FINISHED":
return FINISHED;
default:
return ERROR;
}
}
}
} }

View File

@@ -0,0 +1,49 @@
package com.hccake.starte.pay.ali.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
/**
* 交易状态
*/
public enum TradeStatus {
/**
* 成功
*/
SUCCESS,
/**
* 未支付
*/
WAIT,
/**
* 未付款交易超时关闭,或支付完成后全额退款
*/
CLOSED,
/**
* 交易结束,不可退款
*/
FINISHED,
/**
* 异常. 具体信息查询 subCode和subMsg
*/
ERROR,
;
@JsonCreator
public static TradeStatus of(String status) {
switch (status) {
case "WAIT_BUYER_PAY":
return WAIT;
case "TRADE_CLOSED":
return CLOSED;
case "TRADE_SUCCESS":
return SUCCESS;
case "TRADE_FINISHED":
return FINISHED;
default:
return ERROR;
}
}
}

View File

@@ -17,6 +17,10 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>com.hccake</groupId>
<artifactId>ballcat-common-conf</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.hccake</groupId> <groupId>com.hccake</groupId>
<artifactId>ballcat-spring-boot-starter-pay</artifactId> <artifactId>ballcat-spring-boot-starter-pay</artifactId>

View File

@@ -3,12 +3,15 @@ package com.hccake.sample.pay.ali;
import cn.hutool.core.lang.Snowflake; import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.hccake.starte.pay.ali.AliPay; import com.hccake.starte.pay.ali.AliPay;
import com.hccake.starte.pay.ali.domain.AliPayCallback;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**
@@ -21,18 +24,27 @@ public class Controller {
private final AliPay aliPay; private final AliPay aliPay;
BigDecimal amount = new BigDecimal("100");
BigDecimal zero = new BigDecimal("0.01");
private static final Snowflake snowflake = IdUtil.createSnowflake(1, 1); private static final Snowflake snowflake = IdUtil.createSnowflake(1, 1);
/**
* 支付宝支付回调
* @param callback 回调参数
* @return java.lang.String
* @author lingting 2021-01-26 15:18
*/
@PostMapping @PostMapping
public String notice(Map<String, Object> params) { public String notice(HttpServletRequest request, @RequestParam Map<String, String> callback) {
System.out.println("notice");
AliPayCallback of = AliPayCallback.of(callback);
return "success"; return "success";
} }
@GetMapping @GetMapping
public String debug() { public String debug() {
String sn = snowflake.nextIdStr();
BigDecimal amount = new BigDecimal("100");
// System.out.printf(sn); // System.out.printf(sn);
// aliPay.codePay(sn, amount, "280528061260052112", "测试"); // aliPay.codePay(sn, amount, "280528061260052112", "测试");
return "success"; return "success";

View File

@@ -1,3 +1,7 @@
spring:
application:
name: 支付演示
ballcat: ballcat:
pay: pay:
bitcoin: bitcoin: