modern-in-app-purchase
v1.0.2
Published
Modern in-app purchase validation for Apple and Google using official libraries
Readme
modern-in-app-purchase
A modern, robust, and type-safe in-app purchase validation library for Apple and Google using their official SDKs (@apple/app-store-server-library and googleapis).
Installation
npm install modern-in-app-purchaseUsage with NestJS
This library is designed to be easily integrated into a NestJS application. Below is an example of how to wrap it in a NestJS Service and Module.
1. Create a Configuration Service or use ConfigModule
Ensure you have your Apple and Google credentials available in your environment variables.
2. Create the IAP Service
Create a service to wrap the library's functions.
// in-app-purchase.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import iap, { Platform, Receipt, ValidationResponse } from 'modern-in-app-purchase';
@Injectable()
export class InAppPurchaseService implements OnModuleInit {
constructor(private readonly configService: ConfigService) {}
onModuleInit() {
// Configure the library once when the module initializes
iap.config({
apple: {
issuerId: this.configService.get<string>('APPLE_ISSUER_ID'),
keyId: this.configService.get<string>('APPLE_KEY_ID'),
privateKey: this.configService.get<string>('APPLE_PRIVATE_KEY'),
bundleId: this.configService.get<string>('APPLE_BUNDLE_ID'),
environment: this.configService.get<'Sandbox' | 'Production'>('APPLE_ENVIRONMENT', 'Sandbox'),
},
google: {
clientEmail: this.configService.get<string>('GOOGLE_CLIENT_EMAIL'),
privateKey: this.configService.get<string>('GOOGLE_PRIVATE_KEY').replace(/\\n/g, '\n'),
},
});
}
/**
* Validate a receipt for a given platform
* @param platform 'apple' or 'google'
* @param receipt The receipt data containing transactionId or purchaseToken
*/
async validateReceipt(platform: Platform, receipt: Receipt): Promise<ValidationResponse> {
return await iap.validate(platform, receipt);
}
/**
* Check if a validation response indicates a valid subscription/purchase
*/
isValid(response: ValidationResponse): boolean {
return iap.isValid(response);
}
}3. Create the IAP Module
// in-app-purchase.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { InAppPurchaseService } from './in-app-purchase.service';
@Module({
imports: [ConfigModule],
providers: [InAppPurchaseService],
exports: [InAppPurchaseService],
})
export class InAppPurchaseModule {}4. Use in your Resolver or Controller
// subscription.resolver.ts
import { Resolver, Mutation, Args } from '@nestjs/graphql';
import { InAppPurchaseService } from './in-app-purchase.service';
import { Platform } from 'modern-in-app-purchase';
@Resolver()
export class SubscriptionResolver {
constructor(private readonly iapService: InAppPurchaseService) {}
@Mutation(() => Boolean)
async verifySubscription(
@Args('platform') platform: Platform, // 'apple' or 'google'
@Args('transactionId', { nullable: true }) transactionId?: string, // for Apple
@Args('productId', { nullable: true }) productId?: string, // for Google
@Args('purchaseToken', { nullable: true }) purchaseToken?: string, // for Google
) {
// Validate the receipt
const response = await this.iapService.validateReceipt(platform, {
transactionId,
productId,
purchaseToken,
});
if (this.iapService.isValid(response)) {
// The receipt is valid. Update the user's subscription status in your database.
console.log('Subscription is valid!', response);
return true;
} else {
// The receipt is invalid or expired.
console.log('Subscription validation failed:', response.message);
return false;
}
}
}Types
This library provides full TypeScript support. You can import the types directly:
import {
ConfigOptions,
Platform,
Receipt,
ValidationResponse,
APPLE,
GOOGLE
} from 'modern-in-app-purchase';