1
0
mirror of synced 2026-10-09 16:26:17 +08:00

🎨 消除旧通知头空值重载歧义

This commit is contained in:
Binary Wang
2026-08-18 15:12:04 +08:00
committed by GitHub
parent 509bce53f3
commit dceeaf3b00
3 changed files with 176 additions and 21 deletions

View File

@@ -1,9 +1,9 @@
package com.github.binarywang.wxpay.bean.ecommerce;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
@@ -13,22 +13,13 @@ import java.io.Serializable;
*
* @author cloudX
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Deprecated
public class SignatureHeader implements Serializable {
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = false)
public class SignatureHeader extends com.github.binarywang.wxpay.bean.notify.SignatureHeader implements Serializable {
private static final long serialVersionUID = -6958015499416059949L;
/**
* 时间戳
*/
private String timeStamp;
/**
* 随机串
*/
private String nonce;
/**
* 已签名字符串
@@ -39,4 +30,107 @@ public class SignatureHeader implements Serializable {
* 证书序列号
*/
private String serialNo;
/**
* 保留在旧类中的序列化字段,避免升级后反序列化旧数据时丢失。
*/
private String timeStamp;
/**
* 保留在旧类中的序列化字段,避免升级后反序列化旧数据时丢失。
*/
private String nonce;
public SignatureHeader() {
super();
}
/**
* 保留 4.8.4 及以前版本的构造器签名。
*/
public SignatureHeader(String timeStamp, String nonce, String signed, String serialNo) {
setTimeStamp(timeStamp);
setNonce(nonce);
this.signed = signed;
this.serialNo = serialNo;
}
private SignatureHeader(SignatureHeaderBuilder builder) {
super(builder);
this.timeStamp = builder.timeStamp;
this.nonce = builder.nonce;
this.signed = builder.signed;
this.serialNo = builder.serialNo;
}
@Override
public String getTimeStamp() {
return this.timeStamp;
}
@Override
public void setTimeStamp(String timeStamp) {
super.setTimeStamp(timeStamp);
this.timeStamp = timeStamp;
}
@Override
public String getNonce() {
return this.nonce;
}
@Override
public void setNonce(String nonce) {
super.setNonce(nonce);
this.nonce = nonce;
}
/**
* 保留旧版 builder 的类型和方法返回值描述符。
*/
public static SignatureHeaderBuilder builder() {
return new SignatureHeaderBuilder();
}
public static class SignatureHeaderBuilder extends com.github.binarywang.wxpay.bean.notify.SignatureHeader
.SignatureHeaderBuilder<SignatureHeader, SignatureHeaderBuilder> {
private String timeStamp;
private String nonce;
private String signed;
private String serialNo;
@Override
public SignatureHeaderBuilder timeStamp(String timeStamp) {
super.timeStamp(timeStamp);
this.timeStamp = timeStamp;
return this;
}
@Override
public SignatureHeaderBuilder nonce(String nonce) {
super.nonce(nonce);
this.nonce = nonce;
return this;
}
public SignatureHeaderBuilder signed(String signed) {
this.signed = signed;
return this;
}
public SignatureHeaderBuilder serialNo(String serialNo) {
this.serialNo = serialNo;
return this;
}
@Override
protected SignatureHeaderBuilder self() {
return this;
}
@Override
public SignatureHeader build() {
return new SignatureHeader(this);
}
}
}

View File

@@ -1,9 +1,9 @@
package com.github.binarywang.wxpay.bean.notify;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.io.Serializable;
@@ -14,7 +14,7 @@ import java.io.Serializable;
* @author thinstar
*/
@Data
@Builder
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class SignatureHeader implements Serializable {

View File

@@ -5,8 +5,12 @@ import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.Base64;
/**
* Compile-time compatibility checks for the pre-#4014 e-commerce API.
* Compatibility checks for the pre-#4014 e-commerce API.
*/
public class LegacyEcommerceApiCompatibilityTest {
@@ -25,4 +29,61 @@ public class LegacyEcommerceApiCompatibilityTest {
Assert.assertNotNull(EcommerceService.class.getMethod("parseRefundNotifyResult", String.class, legacyHeader));
Assert.assertNotNull(EcommerceService.class.getMethod("parseWithdrawNotifyResult", String.class, legacyHeader));
}
@Test
public void shouldKeepLegacySignatureHeaderConstructorAndBuilderAbi() throws Exception {
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader legacyHeader =
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.builder()
.timeStamp("timestamp")
.nonce("nonce")
.signed("signed")
.serialNo("serial-no")
.build();
Assert.assertNotNull(com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.class.getConstructor(
String.class, String.class, String.class, String.class));
Assert.assertEquals(com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.SignatureHeaderBuilder.class,
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.SignatureHeaderBuilder.class
.getMethod("timeStamp", String.class).getReturnType());
Assert.assertEquals(com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.SignatureHeaderBuilder.class,
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader.SignatureHeaderBuilder.class
.getMethod("nonce", String.class).getReturnType());
Assert.assertTrue(com.github.binarywang.wxpay.bean.notify.SignatureHeader.class
.isAssignableFrom(legacyHeader.getClass()));
com.github.binarywang.wxpay.bean.notify.SignatureHeader unifiedHeader =
EcommerceService.toUnifiedSignatureHeader(legacyHeader);
Assert.assertEquals(unifiedHeader.getTimeStamp(), "timestamp");
Assert.assertEquals(unifiedHeader.getNonce(), "nonce");
Assert.assertEquals(unifiedHeader.getSignature(), "signed");
Assert.assertEquals(unifiedHeader.getSerial(), "serial-no");
}
@Test
public void shouldIncludeTimestampAndNonceInLegacyHeaderEquality() {
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader first =
new com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader("timestamp-1", "nonce", "signed", "serial-no");
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader second =
new com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader("timestamp-2", "nonce", "signed", "serial-no");
Assert.assertNotEquals(first, second);
}
@Test
public void shouldReadLegacySerializedHeaderFields() throws Exception {
String legacySerializedHeader = "rO0ABXNyADpjb20uZ2l0aHViLmJpbmFyeXdhbmcud3hwYXkuYmVhbi5lY29tbWVyY2UuU2lnbmF0dXJlSGVhZGVyn3ApxLekv9MCAARMAAVub25jZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACHNlcmlhbE5vcQB+AAFMAAZzaWduZWRxAH4AAUwACXRpbWVTdGFtcHEAfgABeHB0AAVub25jZXQACXNlcmlhbC1ub3QABnNpZ25lZHQACXRpbWVzdGFtcA==";
ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(
Base64.getDecoder().decode(legacySerializedHeader)));
com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader header =
(com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader) input.readObject();
Assert.assertEquals(header.getTimeStamp(), "timestamp");
Assert.assertEquals(header.getNonce(), "nonce");
Assert.assertEquals(header.getSigned(), "signed");
Assert.assertEquals(header.getSerialNo(), "serial-no");
}
private void shouldCompileNullNotificationHeaderCalls(EcommerceService ecommerceService) throws Exception {
ecommerceService.parseRefundNotifyResult("notify-data", null);
ecommerceService.parseWithdrawNotifyResult("notify-data", null);
}
}