|
1 | 1 | import { |
| 2 | + AppStoreServerAPIClient, |
| 3 | + ConsumptionStatus, |
| 4 | + DeliveryStatus, |
2 | 5 | Environment, |
3 | 6 | JWSTransactionDecodedPayload, |
| 7 | + LifetimeDollarsPurchased, |
| 8 | + LifetimeDollarsRefunded, |
| 9 | + Platform, |
| 10 | + PlayTime, |
4 | 11 | ResponseBodyV2DecodedPayload, |
| 12 | + UserStatus, |
| 13 | + type ConsumptionRequest, |
5 | 14 | } from '@apple/app-store-server-library'; |
| 15 | +import { RefundPreference } from '@apple/app-store-server-library/dist/models/RefundPreference'; |
| 16 | +import { JsonContains } from 'typeorm'; |
6 | 17 | import type { User } from '../../entity/user/User'; |
7 | 18 | import { |
| 19 | + getAccountTenure, |
8 | 20 | getAnalyticsEventFromAppleNotification, |
9 | 21 | getAppleTransactionType, |
10 | 22 | logAppleAnalyticsEvent, |
11 | 23 | } from './utils'; |
12 | | -import { AppleTransactionType } from './types'; |
| 24 | +import { |
| 25 | + appleAppStoreServerClientKey, |
| 26 | + appleAppStoreServerClientKeyId, |
| 27 | + appleIssuerId, |
| 28 | + AppleTransactionType, |
| 29 | + bundleId, |
| 30 | +} from './types'; |
13 | 31 | import { |
14 | 32 | UserTransaction, |
15 | 33 | UserTransactionProcessor, |
@@ -281,3 +299,62 @@ export const handleCoresPurchase = async ({ |
281 | 299 |
|
282 | 300 | return transaction; |
283 | 301 | }; |
| 302 | + |
| 303 | +export const handleCoresConsumptionRequest = async ({ |
| 304 | + transactionInfo, |
| 305 | + user, |
| 306 | + environment, |
| 307 | +}: { |
| 308 | + transactionInfo: JWSTransactionDecodedPayload; |
| 309 | + user: Pick<User, 'id' | 'subscriptionFlags' | 'coresRole' | 'createdAt'>; |
| 310 | + environment: Environment; |
| 311 | +}) => { |
| 312 | + if (!transactionInfo.transactionId) { |
| 313 | + throw new Error('Missing transactionId in transactionInfo'); |
| 314 | + } |
| 315 | + |
| 316 | + if (!user.subscriptionFlags?.appAccountToken) { |
| 317 | + throw new Error('Missing appAccountToken in user subscription flags'); |
| 318 | + } |
| 319 | + |
| 320 | + const apiClient = new AppStoreServerAPIClient( |
| 321 | + appleAppStoreServerClientKey, |
| 322 | + appleAppStoreServerClientKeyId, |
| 323 | + appleIssuerId, |
| 324 | + bundleId, |
| 325 | + environment, |
| 326 | + ); |
| 327 | + |
| 328 | + const con = await createOrGetConnection(); |
| 329 | + |
| 330 | + const deliveryStatus = await con.getRepository(UserTransaction).exists({ |
| 331 | + where: { |
| 332 | + receiverId: user.id, |
| 333 | + flags: JsonContains({ providerId: transactionInfo.transactionId }), |
| 334 | + }, |
| 335 | + }); |
| 336 | + |
| 337 | + const consumptionRequest: ConsumptionRequest = { |
| 338 | + accountTenure: getAccountTenure(user), |
| 339 | + appAccountToken: user.subscriptionFlags.appAccountToken, |
| 340 | + consumptionStatus: ConsumptionStatus.FULLY_CONSUMED, // It is assumed that the user has fully consumed the in-app purchase |
| 341 | + customerConsented: true, |
| 342 | + deliveryStatus: deliveryStatus |
| 343 | + ? DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY |
| 344 | + : DeliveryStatus.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE, |
| 345 | + refundPreference: RefundPreference.PREFER_DECLINE, |
| 346 | + userStatus: UserStatus.ACTIVE, |
| 347 | + |
| 348 | + // Values we don't track or care about, but are required by Apple |
| 349 | + sampleContentProvided: false, |
| 350 | + lifetimeDollarsPurchased: LifetimeDollarsPurchased.UNDECLARED, |
| 351 | + lifetimeDollarsRefunded: LifetimeDollarsRefunded.UNDECLARED, |
| 352 | + platform: Platform.UNDECLARED, |
| 353 | + playTime: PlayTime.UNDECLARED, |
| 354 | + }; |
| 355 | + |
| 356 | + await apiClient.sendConsumptionData( |
| 357 | + transactionInfo.transactionId, |
| 358 | + consumptionRequest, |
| 359 | + ); |
| 360 | +}; |
0 commit comments