Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Promotional Offer Errors

Able to show the promotional offer, but after going through the payment process, inputting my password, and confirming the purchase, I get an error popup that says "Unable to Purchase. Contact the developer for more information."

In the logs, I get the following errors:

  • SKErrorDomain Code=12 "(null)"
  • ASDServerErrorDomain Code=3903 "Unable to Purchase"

Here are the example parameter values I am passing to the combined string appBundleId + '\u2063' + keyIdentifier + '\u2063' + productIdentifier + '\u2063' + offerIdentifier + '\u2063' + appAccountToken + '\u2063' + nonce + '\u2063' + timestamp

  • appBundleId: com.app.myapp
  • keyIdentifier: copied the key ID from the App Store Connect
  • productIdentifier: product_identifier
  • offerIdentifier: offer_identifier
  • appAccountToken: tried both a UUID and an empty string
  • nonce: a UUID to lowercase
  • timestamp: UNIX timestamp

How I'm generating the signature (Java)

/* promotionalOfferKey = value between "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----" from the downloaded p8 file from App Store Connect associated with the keyIdentifier parameter above */

// stringToSign = the combined string above

byte[] encoded = Base64.getDecoder().decode(promotionalOfferKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
ecdsaSign.initSign(keyFactory.generatePrivate(keySpec));

ecdsaSign.update(stringToSign.getBytes(StandardCharsets.UTF_8));
byte[] signature = ecdsaSign.sign();

signatureToReturn = Base64.getEncoder().encodeToString(signature);

What am I doing wrong? Thank you in advance.

Hi, Did you find a solution to the problem?

We had the same issue in one of our projects. The problem was that our backend used a production key to sign the payload. But for StoreKit testing, you have to use the test key.

To retrieve that key:

  1. Open your .storekit file in Xcode
  2. Go to Editor > Subscription Offers Key
  3. Copy the key and Key ID

Use that key to sign your offers for the sandbox environment.

Hi, Did you find a solution to the problem? I am getting the same problem

Promotional Offer Errors
 
 
Q