Skip to content

Commit ca8ad5a

Browse files
authored
feat: Support Advanced Commerce API
* feat: Add models for Advanced Commerce API * feat: Add advanced commerce errors * feat: API client for Advanced Commerce API * chore: Tests for Advanced Commerce API * chore: Code cleanup * fix: Tests * chore: Minor improvements and updates
1 parent 237e64f commit ca8ad5a

File tree

71 files changed

+3604
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+3604
-356
lines changed

Cargo.toml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[package]
22
name = "app-store-server-library"
3-
description = "The Rust server library for the App Store Server API and App Store Server Notifications"
4-
version = "3.2.0"
3+
description = "The Rust server library for the App Store Server API, App Store Server Notifications and Advanced Commerce API"
4+
version = "4.0.0"
55
repository = "https://github.com/namecare/app-store-server-library-rust"
66
homepage = "https://github.com/namecare/app-store-server-library-rust"
77
authors = ["tkhp", "namecare"]
88
license = "MIT"
99
readme = "README.md"
1010
documentation = "https://docs.rs/app-store-server-library"
11-
keywords = ["apple", "appstore", "appstore-server-api", "appstore-library", "appstore-receipt"]
11+
keywords = ["apple", "appstore", "appstore-server-api", "appstore-receipt", "advanced-commerce"]
1212
edition = "2021"
1313

1414
[dependencies]
@@ -24,7 +24,7 @@ x509-cert = { version = "0.2.5", optional = true }
2424

2525
# Serialization
2626
serde = { version = "1.0.219", features = ["derive"] }
27-
serde_json = { version = "1.0.142" }
27+
serde_json = { version = "1.0.143" }
2828
serde_with = { version = "3.14.0", features = ["chrono"] }
2929
serde_repr = "0.1.20"
3030
uuid = { version = "1.18.0", features = ["serde", "v4"] }
@@ -36,10 +36,10 @@ reqwest = { version = "0.12.23", default-features = false, features = ["json"],
3636
http = { version = "1.3.1", optional = true }
3737

3838
# Utils
39-
thiserror = "2.0.15"
39+
thiserror = "2.0.16"
4040

4141
# Tools
42-
regex = { version = "1.11.1", optional = true }
42+
regex = { version = "1.11.2", optional = true }
4343

4444
[dev-dependencies]
4545

@@ -54,8 +54,13 @@ receipt-utility = ["dep:regex"]
5454
ocsp = ["dep:x509-ocsp", "dep:x509-cert", "dep:reqwest", "reqwest/blocking", "dep:der"]
5555

5656
[[test]]
57-
name = "api_client"
58-
path = "tests/api_client.rs"
57+
name = "ass_api_client"
58+
path = "tests/ass_api_client.rs"
59+
required-features = ["api-client"]
60+
61+
[[test]]
62+
name = "ac_api_client"
63+
path = "tests/ac_api_client.rs"
5964
required-features = ["api-client"]
6065

6166
[[test]]

README.md

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Apple App Store Server Rust Library
2-
The Rust server library for the [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi) and [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications)
2+
The Rust server library for the [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi), [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications) and [Advanced Commerce API](https://developer.apple.com/documentation/AdvancedCommerceAPI).
33

44
## Requirements
55

@@ -11,12 +11,12 @@ Specify `app-store-server-library` in your project's `Cargo.toml` file, under th
1111

1212
```toml
1313
[dependencies]
14-
app-store-server-library = { version = "3.2.0", features = ["receipt-utility", "api-client", "ocsp"] }
14+
app-store-server-library = { version = "4.0.0", features = ["receipt-utility", "api-client", "ocsp"] }
1515
```
1616

1717
### Feature Flags
1818

19-
- `api-client` - Enables the App Store Server API client functionality
19+
- `api-client` - Enables the App Store Server/Advanced Commerce API client functionality
2020
- `receipt-utility` - Enables receipt processing and transaction ID extraction
2121
- `ocsp` - Enables OCSP (Online Certificate Status Protocol) verification
2222

@@ -34,6 +34,7 @@ Download and store the root certificates found in the Apple Root Certificates se
3434

3535
### API Usage
3636

37+
#### App Store Server API
3738
```rust
3839
use app_store_server_library::{AppStoreServerApiClient, Environment, AppStoreApiResponse, APIError};
3940

@@ -44,15 +45,48 @@ async fn main() {
4445
let bundle_id = "com.example";
4546
let encoded_key = std::fs::read_to_string("/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8").unwrap(); // Adjust the path accordingly
4647
let environment = Environment::Sandbox;
47-
48-
let client = AppStoreServerApiClient::new(encoded_key, key_id, issuer_id, bundle_id, environment);
48+
let transport = ReqwestHttpTransport::new(); // You can use any http client, but you must implement `Transport` trait for it.
49+
let client = AppStoreServerApiClient::new(encoded_key, key_id, issuer_id, bundle_id, environment, transport);
4950
match client.request_test_notification().await {
5051
Ok(response) => {
5152
println!("{}", response.test_notification_token);
5253
}
5354
Err(err) => {
5455
println!("{}", err.http_status_code);
55-
println!("{:?}", err.raw_api_error);
56+
println!("{:?}", err.error_code);
57+
println!("{:?}", err.api_error);
58+
println!("{}", err.error_message);
59+
}
60+
}
61+
}
62+
```
63+
64+
#### Advanced Commerce Server API
65+
```rust
66+
// NOTE: .unwrap() used for example purposes only
67+
68+
use app_store_server_library::{AppStoreServerApiClient, Environment, AppStoreApiResponse, APIError};
69+
70+
#[tokio::main]
71+
async fn main() {
72+
let issuer_id = "99b16628-15e4-4668-972b-eeff55eeff55";
73+
let key_id = "ABCDEFGHIJ";
74+
let bundle_id = "com.example";
75+
let encoded_key = std::fs::read_to_string("/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8").unwrap(); // Adjust the path accordingly
76+
let environment = Environment::Sandbox;
77+
let transport = ReqwestHttpTransport::new(); // You can use any http client, but you must implement `Transport` trait for it.
78+
let client = AdvancedCommerceApiClient::new(encoded_key, key_id, issuer_id, bundle_id, environment, transport);
79+
80+
let transaction_id = "txId";
81+
let subscription_cancel_request = SubscriptionCancelRequest(...);
82+
match client.cancel_subscription(transaction_id, &subscription_cancel_request).await {
83+
Ok(response) => {
84+
println!("{}", response.signed_renewal_info);
85+
println!("{}", response.signed_transaction_info);
86+
}
87+
Err(err) => {
88+
println!("{}", err.http_status_code);
89+
println!("{:?}", err.error_code);
5690
println!("{:?}", err.api_error);
5791
println!("{}", err.error_message);
5892
}
@@ -63,7 +97,8 @@ async fn main() {
6397
### Verification Usage
6498

6599
```rust
66-
// .unwrap() used for example purposes only
100+
// NOTE: .unwrap() used for example purposes only
101+
67102
let root_cert = "apple-root-cert-in-base-base64-format"; // https://www.apple.com/certificateauthority/AppleRootCA-G3.cer
68103
let root_cert_der = root_cert.as_der_bytes().unwrap(); // Use `base64` crate to decode base64 string into bytes
69104

@@ -86,11 +121,14 @@ To enable OCSP verification:
86121

87122
```toml
88123
[dependencies]
89-
app-store-server-library = { version = "3.2.0", features = ["api-client", "ocsp"] }
124+
app-store-server-library = { version = "4.0.0", features = ["ocsp"] }
90125
```
91126

92127
OCSP verification is performed automatically when verifying signed data.
93128

129+
> Note: OCSP request is blocking, not async.
130+
> Async signed data verification is coming soon.
131+
94132
### Receipt Usage
95133
```rust
96134
let receipt = "MI..";
@@ -102,9 +140,10 @@ let transaction_id = extract_transaction_id_from_app_receipt(receipt);
102140

103141
#### V1 Signature Creation
104142
```rust
143+
// NOTE: .unwrap() used for example purposes only
144+
105145
use app_store_server_library::promotional_offer::PromotionalOfferSignatureCreator;
106146

107-
// .unwrap() used for example purposes only
108147
let private_key = include_str!("../assets/SubscriptionKey_L256SYR32L.p8");
109148
let creator = PromotionalOfferSignatureCreator::new(private_key, "L256SYR32L".to_string(), "com.test.app".to_string()).unwrap();
110149

@@ -121,9 +160,10 @@ let signature: String = creator.create_signature(
121160

122161
#### V2 Signature Creation
123162
```rust
124-
use app_store_server_library::promotional_offer_v2::PromotionalOfferV2SignatureCreator;
163+
// NOTE: .unwrap() used for example purposes only
125164

126-
// .unwrap() used for example purposes only
165+
use app_store_server_library::promotional_offer_v2::PromotionalOfferV2SignatureCreator;
166+
127167
let private_key = include_str!("../assets/SubscriptionKey_L256SYR32L.p8");
128168
let creator = PromotionalOfferV2SignatureCreator::new(
129169
private_key,
@@ -139,11 +179,39 @@ let signature: String = creator.create_signature(
139179
).unwrap();
140180
```
141181

182+
### Advanced Commerce Signature Creation
183+
184+
#### Prepare request object:
185+
- Receive request object from the client.
186+
- Or create request from the server side.
187+
188+
Supported request objects: `OneTimeChargeCreateRequest`, `SubscriptionCreateRequest`, `SubscriptionModifyInAppRequest` or `SubscriptionReactivateInAppRequest`.
189+
190+
```rust
191+
// NOTE: .unwrap() used for example purposes only
192+
193+
use app_store_server_library::promotional_offer_v2::PromotionalOfferV2SignatureCreator;
194+
195+
let request_object = ... // Receive from client side or create on server side
196+
let private_key = include_str!("../assets/SubscriptionKey_L256SYR32L.p8");
197+
let creator = AdvancedCommerceInAppSignatureCreator::new(
198+
private_key,
199+
"L256SYR32L".to_string(), // Key ID
200+
"issuer_id".to_string(), // Issuer ID
201+
"com.test.app".to_string() // Bundle ID
202+
).unwrap();
203+
204+
let signature: String = creator.create_signature(
205+
advanced_commerce_in_app_request: &request_object
206+
).unwrap();
207+
```
208+
142209
## Documentation
143210

144211
* The full documentation is available at [docs.rs](https://docs.rs/app-store-server-library/)
145212
* [App Store Server API Documentation](https://developer.apple.com/documentation/appstoreserverapi)
146213
* [App Store Server Notifications Documentation](https://developer.apple.com/documentation/appstoreservernotifications)
214+
* [Advanced Commerce API Documentation](https://developer.apple.com/documentation/advancedcommerceapi)
147215
* [WWDC Video](https://developer.apple.com/videos/play/wwdc2023/10143/)
148216

149217
## References

0 commit comments

Comments
 (0)