Skip to content

Commit 007174d

Browse files
authored
feat: Adding support for Get App Transaction Info endpoint (#86)
1 parent 1ff2456 commit 007174d

File tree

9 files changed

+145
-0
lines changed

9 files changed

+145
-0
lines changed

src/api_client/api/app_store_server_api.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::api_client::api::app_store_server_api::api_error_code::ApiErrorCode;
77
use crate::api_client::api_client::{ApiClient};
88
use crate::api_client::error::ApiServiceError;
99
use crate::api_client::transport::Transport;
10+
use crate::primitives::app_transaction_info_response::AppTransactionInfoResponse;
1011
use crate::primitives::check_test_notification_response::CheckTestNotificationResponse;
1112
use crate::primitives::consumption_request::ConsumptionRequest;
1213
use crate::primitives::extend_renewal_date_request::ExtendRenewalDateRequest;
@@ -410,6 +411,27 @@ impl<T: Transport> AppStoreServerApiClient<T> {
410411
self.make_request_with_response_body(req).await
411412
}
412413

414+
/// Get a customer's app transaction information for your app.
415+
///
416+
/// [Get App Transaction Info](https://developer.apple.com/documentation/appstoreserverapi/get-app-transaction-info)
417+
///
418+
/// # Arguments
419+
///
420+
/// * `transaction_id` - Any originalTransactionId, transactionId or appTransactionId that belongs to the customer for your app.
421+
///
422+
/// # Returns
423+
///
424+
/// A response that contains signed app transaction information for a customer.
425+
///
426+
/// # Errors
427+
///
428+
/// Returns an `APIError` if the request could not be processed.
429+
pub async fn app_transaction_info(&self, transaction_id: &str) -> Result<AppTransactionInfoResponse, ApiError> {
430+
let path = format!("/inApps/v1/transactions/appTransactions/{}", transaction_id);
431+
let req = self.build_request::<()>(path.as_str(), Method::GET, None)?;
432+
self.make_request_with_response_body(req).await
433+
}
434+
413435
/// Get a customer's in-app purchases from a receipt using the order ID.
414436
///
415437
/// [Documentation](https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id)

src/api_client/api/app_store_server_api/api_error_code.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ pub enum ApiErrorCode {
239239
/// [Documentation](https://developer.apple.com/documentation/appstoreserverapi/transactionidnotfounderror)
240240
TransactionIdNotFound = 4040010,
241241

242+
/// An error response that indicates an app transaction doesn't exist for the specified customer.
243+
///
244+
/// [AppTransactionDoesNotExistError](https://developer.apple.com/documentation/appstoreserverapi/apptransactiondoesnotexisterror)
245+
AppTransactionDoesNotExist = 4040019,
246+
242247
/// An error that indicates that the request exceeded the rate limit.
243248
/// [Documentation](https://developer.apple.com/documentation/appstoreserverapi/ratelimitexceedederror)
244249
RateLimitExceeded = 4290000,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2025 Apple Inc. Licensed under MIT License.
2+
3+
use serde::{Deserialize, Serialize};
4+
5+
/// A response that contains signed app transaction information for a customer.
6+
///
7+
/// [AppTransactionInfoResponse](https://developer.apple.com/documentation/appstoreserverapi/apptransactioninforesponse)
8+
#[derive(Debug, Clone, Deserialize, Serialize, Hash)]
9+
pub struct AppTransactionInfoResponse {
10+
/// A customer's app transaction information, signed by Apple, in JSON Web Signature (JWS) format.
11+
///
12+
/// [JWSAppTransaction](https://developer.apple.com/documentation/appstoreserverapi/jwsapptransaction)
13+
#[serde(rename = "signedAppTransactionInfo")]
14+
pub signed_app_transaction_info: Option<String>,
15+
}

src/primitives/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod account_tenure;
22
pub mod app_transaction;
3+
pub mod app_transaction_info_response;
34
pub mod auto_renew_status;
45
pub mod check_test_notification_response;
56
pub mod consumption_request;

tests/ass_api_client.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,93 @@ async fn test_get_transaction_info() {
632632
);
633633
}
634634

635+
#[tokio::test]
636+
async fn test_app_transaction_info() {
637+
let client = app_store_server_api_client_with_body_from_file(
638+
"tests/resources/models/appTransactionInfoResponse.json",
639+
StatusCode::OK,
640+
Some(Box::new(|req, body| {
641+
assert_eq!(&Method::GET, req.method());
642+
assert_eq!(
643+
"https://local-testing-base-url/inApps/v1/transactions/appTransactions/1234",
644+
req.uri().to_string()
645+
);
646+
assert!(body.is_empty(), "GET request should have empty body");
647+
})),
648+
);
649+
650+
let response = client
651+
.app_transaction_info("1234")
652+
.await
653+
.unwrap();
654+
assert_eq!(
655+
"signed_app_transaction_info_value",
656+
response
657+
.signed_app_transaction_info
658+
.unwrap()
659+
);
660+
}
661+
662+
#[tokio::test]
663+
async fn test_app_transaction_info_invalid_transaction_id() {
664+
let client = app_store_server_api_client_with_body_from_file(
665+
"tests/resources/models/invalidTransactionIdError.json",
666+
StatusCode::BAD_REQUEST,
667+
None,
668+
);
669+
670+
let result = client
671+
.app_transaction_info("invalid_id")
672+
.await;
673+
674+
assert!(result.is_err());
675+
let err = result.unwrap_err();
676+
assert_eq!(400, err.http_status_code);
677+
assert_eq!(Some(ApiErrorCode::InvalidTransactionId), err.api_error);
678+
assert_eq!(Some(4000006), err.error_code);
679+
assert_eq!(Some("Invalid transaction id.".to_string()), err.error_message);
680+
}
681+
682+
#[tokio::test]
683+
async fn test_app_transaction_info_transaction_id_not_found() {
684+
let client = app_store_server_api_client_with_body_from_file(
685+
"tests/resources/models/transactionIdNotFoundError.json",
686+
StatusCode::NOT_FOUND,
687+
None,
688+
);
689+
690+
let result = client
691+
.app_transaction_info("not_found_id")
692+
.await;
693+
694+
assert!(result.is_err());
695+
let err = result.unwrap_err();
696+
assert_eq!(404, err.http_status_code);
697+
assert_eq!(Some(ApiErrorCode::TransactionIdNotFound), err.api_error);
698+
assert_eq!(Some(4040010), err.error_code);
699+
assert_eq!(Some("Transaction id not found.".to_string()), err.error_message);
700+
}
701+
702+
#[tokio::test]
703+
async fn test_app_transaction_info_app_transaction_does_not_exist() {
704+
let client = app_store_server_api_client_with_body_from_file(
705+
"tests/resources/models/appTransactionDoesNotExistError.json",
706+
StatusCode::NOT_FOUND,
707+
None,
708+
);
709+
710+
let result = client
711+
.app_transaction_info("no_app_transaction")
712+
.await;
713+
714+
assert!(result.is_err());
715+
let err = result.unwrap_err();
716+
assert_eq!(404, err.http_status_code);
717+
assert_eq!(Some(ApiErrorCode::AppTransactionDoesNotExist), err.api_error);
718+
assert_eq!(Some(4040019), err.error_code);
719+
assert_eq!(Some("No AppTransaction exists for the customer.".to_string()), err.error_message);
720+
}
721+
635722
#[tokio::test]
636723
async fn test_look_up_order_id() {
637724
let client = app_store_server_api_client_with_body_from_file(
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"errorCode": 4040019,
3+
"errorMessage": "No AppTransaction exists for the customer."
4+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"signedAppTransactionInfo": "signed_app_transaction_info_value"
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"errorCode": 4000006,
3+
"errorMessage": "Invalid transaction id."
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"errorCode": 4040010,
3+
"errorMessage": "Transaction id not found."
4+
}

0 commit comments

Comments
 (0)