Skip to main content

3.3.5 - External Payments Program (Japan)

· 3 min read
Hyo
Expo IAP Maintainer

Expo IAP 3.3.5 brings Google Play Billing Library 8.3.0 support with the new External Payments program for Japan.

New Features

External Payments Program (Android 8.3.0+, Japan Only)

The External Payments program introduces a side-by-side choice between Google Play Billing and the developer's external payment option directly in the purchase flow.

Key Differences from User Choice Billing

FeatureUser Choice BillingExternal Payments
Billing Library7.0+8.3.0+
AvailabilityEligible regionsJapan only
When presentedAfter initConnection()During requestPurchase()
UISeparate dialogSide-by-side choice in purchase dialog
ListeneruserChoiceBillingListenerAndroiddeveloperProvidedBillingListenerAndroid

New APIs

developerProvidedBillingListenerAndroid()

New listener that fires when a user selects the developer's payment option in the External Payments dialog.

import {developerProvidedBillingListenerAndroid} from 'expo-iap';

const subscription = developerProvidedBillingListenerAndroid(async (details) => {
console.log('User selected developer billing');
console.log('Token:', details.externalTransactionToken);

// Process payment with your gateway
await processPaymentWithYourGateway(details.externalTransactionToken);

// IMPORTANT: Report to Google within 24 hours
await reportExternalTransactionToGoogle(details.externalTransactionToken);
});

// Clean up
subscription.remove();

OpenIapEvent.DeveloperProvidedBillingAndroid

New event type for the External Payments flow.

import {OpenIapEvent} from 'expo-iap';

// Event: 'developer-provided-billing-android'
console.log(OpenIapEvent.DeveloperProvidedBillingAndroid);

BillingProgramAndroid.ExternalPayments

New billing program type for External Payments.

import {isBillingProgramAvailableAndroid} from 'expo-iap';

// Check if External Payments is available (Japan only)
const result = await isBillingProgramAvailableAndroid('external-payments');
if (result.isAvailable) {
// External Payments is available for this user
}

New Types

// Developer billing option for purchase requests
interface DeveloperBillingOptionParamsAndroid {
billingProgram: BillingProgramAndroid; // should be 'external-payments'
linkUri: string;
launchMode: DeveloperBillingLaunchModeAndroid;
}

// Launch mode options
type DeveloperBillingLaunchModeAndroid =
| 'unspecified'
| 'launch-in-external-browser-or-app'
| 'caller-will-launch-link';

// Details received when user selects developer billing
interface DeveloperProvidedBillingDetailsAndroid {
externalTransactionToken: string;
}

// Updated BillingProgramAndroid
type BillingProgramAndroid =
| 'unspecified'
| 'external-content-link'
| 'external-offer'
| 'external-payments'; // New in 8.3.0

Complete External Payments Flow Example

import {useEffect} from 'react';
import {
initConnection,
isBillingProgramAvailableAndroid,
developerProvidedBillingListenerAndroid,
requestPurchase,
} from 'expo-iap';
import {Platform} from 'react-native';

export default function ExternalPaymentsComponent() {
useEffect(() => {
if (Platform.OS !== 'android') return;

const initialize = async () => {
// Initialize with External Payments program
await initConnection({
enableBillingProgramAndroid: 'external-payments',
});

// Check availability (Japan only)
const result = await isBillingProgramAvailableAndroid('external-payments');
if (!result.isAvailable) {
console.log('External Payments not available');
return;
}

// Set up listener for when user selects developer billing
const subscription = developerProvidedBillingListenerAndroid(
async (details) => {
console.log('User selected developer billing');

// Process payment with your gateway
await processPayment(details.externalTransactionToken);

// Report to Google within 24 hours
await reportToGoogle(details.externalTransactionToken);
},
);

return () => subscription.remove();
};

const cleanup = initialize();
return () => {
cleanup.then((fn) => fn?.());
};
}, []);

const purchaseWithExternalPayments = async (sku: string) => {
// Request purchase with developer billing option
await requestPurchase({
request: {
google: {
skus: [sku],
developerBillingOption: {
billingProgram: 'external-payments',
linkUri: 'https://your-payment-site.com/checkout',
launchMode: 'launch-in-external-browser-or-app',
},
},
},
type: 'in-app',
});
};

// Rest of component
}

OpenIAP Updates

  • openiap-google: 1.3.16 → 1.3.18
  • openiap-gql: 1.3.8 → 1.3.9

Installation

bun add expo-iap@3.3.5
# or
npm install expo-iap@3.3.5
# or
yarn add expo-iap@3.3.5

References

Questions or feedback? Reach out via GitHub issues.