Unoffical PHP client for App Store Server API and App Store Server Notifications.
- PHP >= 7.2
composer require nullform/app-store-server-api-clientCreate an API Key instance:
// As instance of anonymous class...
$apiKey = new class extends AbstractApiKey {};
$apiKey->setPrivateKey(\file_get_contents($privateKeyFile));
$apiKey->setPrivateKeyId('Your private key id');
$apiKey->setIssuerId('Your issuer id');
$apiKey->setName('Key name (optional)');
// ... or as instance of ApiKey
$apiKey = new ApiKey(
    \file_get_contents($privateKeyFile),
    'Your private key id',
    'Your issuer id',
    'Key name (optional)'
);Create a Bundle instance(s):
// As instance of anonymous class...
$bundle = new class extends AbstractBundle {};
$bundle->setBundleId('Your bundle id');
$bundle->setName('Bundle name (optional)');
// ... or as instance of Bundle
$bundle2 = new Bundle('Your bundle #2 id');Create an API client instance:
$client = new AppStoreServerApiClient($apiKey, $bundle, Environment::PRODUCTION);Use client for one or multiple bundles:
try {
    $historyResponse = $client->getTransactionHistory($originalTransactionId);
    $transactions = $historyResponse->getDecodedTransactions();
} catch (HttpClientException $httpClientException) {
    echo "HTTP client error: " . $httpClientException->getMessage();
} catch (AppleException $appleException) {
    echo "Apple error ({$appleException->getCode()}): " . $appleException->getMessage();
}
try {
    $bundle2HistoryResponse = $client->setBundle($bundle2)->getTransactionHistory($originalTransactionId);
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}You can manually call the App Store Server API via universal callApi() method:
use Nullform\AppStoreServerApiClient\AppStoreServerApiClient;
use Nullform\AppStoreServerApiClient\AbstractModel;
use Nullform\AppStoreServerApiClient\Environment;
$apiKey = new MyApiKey(); // Extends AbstractApiKey
$bundle = new MyBundle(); // Extends AbstractBundle
$client = new AppStoreServerApiClient($apiKey, $bundle, Environment::SANDBOX);
$queryParams = new class extends AbstractModel {
    public $param = 'value';
};
$requestBody = new class extends AbstractModel {
    public $bodyParam = 'value';
};
// Get instance of ResponseInterface
$response = $client->callApi("POST", "inApps/v1/notifications/test", $queryParams, $requestBody);
// Get response body
$responseBody = $response->getBody()->getContents();AppStoreServerApiClient::getTransactionHistory(
    string $transactionId,
    null|string|GetTransactionHistoryParams $paramsOrRevision = null
): HistoryResponseGet a customer’s in-app purchase transaction history for your app.
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
AppStoreServerApiClient::getAllTransactionHistory(
    string $transactionId
): JWSTransactionDecodedPayload[]Recursively get FULL transaction history.
AppStoreServerApiClient::getTransactionInfo(
    string $transactionId
): TransactionInfoResponseGet information about a single transaction for your app.
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info
AppStoreServerApiClient::getAllSubscriptionStatuses(
    string $transactionId
): StatusResponseGet the statuses for all of a customer’s subscriptions in your app.
https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses
AppStoreServerApiClient::sendConsumptionInformation(
    string $transactionId,
    ConsumptionRequest $request
): voidSend consumption information about a consumable in-app purchase to the App Store after your server receives a consumption request notification.
https://developer.apple.com/documentation/appstoreserverapi/send_consumption_information
AppStoreServerApiClient::lookUpOrderId(
    string $orderId
): OrderLookupResponseGet a customer’s in-app purchases from a receipt using the order ID.
https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id
AppStoreServerApiClient::getRefundHistory(
    string $transactionId
): RefundLookupResponseGet a list of all refunded in-app purchases in your app for a customer.
https://developer.apple.com/documentation/appstoreserverapi/get_refund_history
AppStoreServerApiClient::extendSubscriptionRenewalDate(
    string $originalTransactionId,
    ExtendRenewalDateRequest $request
): ExtendRenewalDateResponseExtend the renewal date of a customer’s active subscription using the original transaction identifier.
https://developer.apple.com/documentation/appstoreserverapi/extend_a_subscription_renewal_date
AppStoreServerApiClient::extendSubscriptionRenewalDatesForAllActiveSubscribers(
    MassExtendRenewalDateRequest $request
): MassExtendRenewalDateResponseUses a subscription’s product identifier to extend the renewal date for all of its eligible active subscribers.
AppStoreServerApiClient::getStatusOfSubscriptionRenewalDateExtensions(
    string $productId,
    string $requestIdentifier
): MassExtendRenewalDateStatusResponseChecks whether a renewal date extension request completed, and provides the final count of successful or failed extensions.
AppStoreServerApiClient::requestTestNotification(): SendTestNotificationResponseAsk App Store Server Notifications to send a test notification to your server.
https://developer.apple.com/documentation/appstoreserverapi/request_a_test_notification
AppStoreServerApiClient::getTestNotificationStatus(
    string $testNotificationToken
): CheckTestNotificationResponseCheck the status of the test App Store server notification sent to your server.
https://developer.apple.com/documentation/appstoreserverapi/get_test_notification_status
AppStoreServerApiClient::getNotificationHistory(
    NotificationHistoryRequest $params,
    ?string $paginationToken = null
): CheckTestNotificationResponseGet a list of notifications that the App Store server attempted to send to your server.
https://developer.apple.com/documentation/appstoreserverapi/get_notification_history
AppStoreServerApiClient::setBundle(
    BundleInterface $bundle
): selfSet App Store bundle for authorize your API calls.
AppStoreServerApiClient::setTokenTtl(
    int $ttl
): selfSet new value for JWT TTL (in seconds). Maximum value: 3600.
https://developer.apple.com/documentation/appstoreserverapi/generating_tokens_for_api_requests
AppStoreServerApiClient::setHttpClientRequestTimeout(
    float $timeout
): selfSet new value for HTTP client request timeout (in seconds).
AppStoreServerApiClient::callApi(
    string $method,
    string $path,
    ?AbstractModel $params = null,
    ?AbstractModel $body = null
): \Psr\Http\Message\ResponseInterfaceCustom call App Store Server API with your previously passed credentials.
To receive App Store Server Notifications use AppStoreServerNotificationsClient:
$notificationClient = new AppStoreServerNotificationsClient();
try {
    $payload = $notificationClient->receive($requestBody);
} catch (NotificationBadRequestException $exception) {
    echo $exception->getMessage();
}Note that AppStoreServerNotificationsClient only for version 2 notifications.
For unit tests you must create credentials.php and private-key.p8 with the key and sandbox credentials from App Store Connect (see tests/credentials.example.php).