Verification failed with status INVALID_CHAIN_LENGTH

我正在通过集成app-store-server-library-java来实现 iap服务端校验。我参照了官网提供的Verification Usage 的代码,运行的时候异常信息如下:

	at com.apple.itunes.storekit.verification.ChainVerifier.verifyChainWithoutCaching(ChainVerifier.java:98)
	at com.apple.itunes.storekit.verification.ChainVerifier.verifyChain(ChainVerifier.java:71)
	at com.apple.itunes.storekit.verification.SignedDataVerifier.decodeSignedObject(SignedDataVerifier.java:186)
	at com.apple.itunes.storekit.verification.SignedDataVerifier.verifyAndDecodeTransaction(SignedDataVerifier.java:72)

我的代码如下:

import com.apple.itunes.storekit.model.ResponseBodyV2DecodedPayload;
import com.apple.itunes.storekit.verification.SignedDataVerifier;
import com.apple.itunes.storekit.verification.VerificationException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Set;

public class ExampleVerification {
    public static void main(String[] args) throws FileNotFoundException {
        String bundleId = "com.example";
        Environment environment = Environment.SANDBOX;
        Set<InputStream> rootCAs = Set.of(
                new FileInputStream("AppleRootCA-G3.cer"),
                new FileInputStream("AppleRootCA-G2.cer")
        );
        Long appAppleId = null; // appAppleId must be provided for the Production environment

        SignedDataVerifier signedPayloadVerifier = new SignedDataVerifier(rootCAs, bundleId, appAppleId, environment, true);

        String appTransactionJWS = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkFwcGxlX1hjb2RlX0tleSIsIng1YyI6WyJNSUlCeXpDQ0FYR2dBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakJJTVNJd0lBWURWUVFERXhsVGRHOXlaVXRwZENCVVpYTjBhVzVuSUdsdUlGaGpiMlJsTVNJd0lBWURWUVFLRXhsVGRHOXlaVXRwZENCVVpYTjBhVzVuSUdsdUlGaGpiMlJsTUI0WERUSTFNRFl3TXpFeE1UQXdNRm9YRFRJMk1EWXdNekV4TVRBd01Gb3dTREVpTUNBR0ExVUVBeE1aVTNSdmNtVkxhWFFnVkdWemRHbHVaeUJwYmlCWVkyOWtaVEVpTUNBR0ExVUVDaE1aVTNSdmNtVkxhWFFnVkdWemRHbHVaeUJwYmlCWVkyOWtaVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCTnZZZ3o1MW1CbEMweE5McW9rMUJCcithRWJEb1ZEeVkyaVRsejZsK1JjYVR4QStVY2ptMjBESTNncFFlM280a2doRGxSbGowdEo1enBGUHgyQWR2VCtqVERCS01CSUdBMVVkRXdFQlwvd1FJTUFZQkFmOENBUUF3SkFZRFZSMFJCQjB3RzRFWlUzUnZjbVZMYVhRZ1ZHVnpkR2x1WnlCcGJpQllZMjlrWlRBT0JnTlZIUThCQWY4RUJBTUNCNEF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQU40bUJWTHBoZkpjYjdweHF2b09XcjkyK1czYU5LRG9pazV5Vk9BT0NEVmxBaUFYWVF0czJubWZGMStGYzlSODJHXC96QWhaVU00aDNTXC9VdFE4Q1lPS2p3ZlE9PSJdfQ.eyJhcHBsaWNhdGlvblZlcnNpb24iOiIxIiwib3JpZ2luYWxQdXJjaGFzZURhdGUiOjAsImJ1bmRsZUlkIjoiYnJpZ2h0LnVuaWhhbmQuY24iLCJhcHBUcmFuc2FjdGlvbklkIjoiMCIsImRldmljZVZlcmlmaWNhdGlvbiI6IlRYdGRvMWZtNDhQVDdXUUh5cHU4K2l3TW55YmNoTTNNeG5XUnhOR1JqSFhQQnVqMXdUaldcL05zN3JtUmJlQTd3IiwicmVjZWlwdFR5cGUiOiJYY29kZSIsIm9yaWdpbmFsQXBwbGljYXRpb25WZXJzaW9uIjoiMSIsInJlcXVlc3REYXRlIjoxNzYxMDM1OTMzNTE3LCJvcmlnaW5hbFBsYXRmb3JtIjoiaU9TIiwicmVjZWlwdENyZWF0aW9uRGF0ZSI6MTc2MTAzNTkzMzUxNywiZGV2aWNlVmVyaWZpY2F0aW9uTm9uY2UiOiI1ZDhmNzM5Mi01N2YwLTQyM2YtOTMzNy1hZDQ0YTk5MDM4Y2EifQ.2ZO5xsx-yywP4IyaDz4KQ3mq181ZGwlX2uANSm-kHq50KIdMMUDveMsCrcZmHdzLH2rpfPsXKaIMdM25Hdcuuw";
        DecodedJWT unverifiedJWT = JWT.decode(appTransactionJWS);
        String header = unverifiedJWT.getHeader();
        System.out.println(new String(Base64.getDecoder().decode(header)));
        
        try {
            signedPayloadVerifier.verifyAndDecodeTransaction(appTransactionJWS);
        } catch (VerificationException e) {
            e.printStackTrace();
        }
    }
}

查看了ChainVerifier.java 源代码,发现

private static final int EXPECTED_CHAIN_LENGTH = 3; // <--- 关键常量

// ...

PublicKey verifyChainWithoutCaching(String[] certificates, boolean performRevocationChecking, Date effectiveDate) throws VerificationException {
    // ... 解析证书代码 ...

    if (parsedCertificates.size() != EXPECTED_CHAIN_LENGTH) {
        throw new VerificationException(VerificationStatus.INVALID_CHAIN_LENGTH); // <--- 抛出异常点
    }

    // ... 后续验证代码 ...
}

appTransactionJWS是来自客户端的沙盒环境。 我发现沙盒环境的jws总是包含一个证书,而后端验证又必须要求三个证书,请问这个问题如何解决。

Verification failed with status INVALID_CHAIN_LENGTH
 
 
Q