Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions packages/docs/src/components/Callout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { ReactNode } from 'react';

type CalloutKind = 'note' | 'tip' | 'important' | 'warning';

const KIND_LABELS: Record<CalloutKind, string> = {
note: 'Note',
tip: 'Tip',
important: 'Important',
warning: 'Warning',
};

interface CalloutProps {
kind?: CalloutKind;
title?: string;
children: ReactNode;
}

function Callout({ kind = 'note', title, children }: CalloutProps) {
return (
<aside className={`callout callout--${kind}`}>
<p className="callout-label">{title ?? KIND_LABELS[kind]}</p>
<div className="callout-body">{children}</div>
</aside>
);
}

export default Callout;
112 changes: 38 additions & 74 deletions packages/docs/src/pages/docs/android-setup.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Callout from '../../components/Callout';
import SEO from '../../components/SEO';
import { GOOGLE_PLAY_BILLING, OPENIAP_VERSIONS } from '../../lib/versioning';

Expand All @@ -13,25 +14,12 @@ function AndroidSetup() {
<h1>Android Setup Guide</h1>
<p>
Setting up in-app purchases for Android requires configuration in Google
Play Console and your Android project.
Play Console and your Android project. Building for another
Android-compatible store? See{' '}
<a href="/docs/setup/store">Store Setup</a> for Horizon OS, Fire OS,
Vega OS, and alternative marketplace targets.
</p>

<div
style={{
padding: '1rem',
background: 'rgba(33, 150, 243, 0.1)',
borderLeft: '4px solid #2196F3',
borderRadius: '0.5rem',
margin: '1rem 0',
}}
>
<strong>📱 Building for another Android-compatible store?</strong> See{' '}
<a href="/docs/setup/store" className="external-link">
Store Setup
</a>
for Horizon OS, Fire OS, Vega OS, and alternative marketplace targets.
</div>

<section>
<h2 id="prerequisites" className="anchor-heading">
Prerequisites
Expand Down Expand Up @@ -76,19 +64,11 @@ function AndroidSetup() {
</li>
</ul>

<div
style={{
padding: '1rem',
background: 'rgba(220, 104, 67, 0.1)',
borderLeft: '4px solid var(--accent-color)',
borderRadius: '0.5rem',
margin: '1rem 0',
}}
>
<strong>⚠️ Important:</strong> The merchant account must be fully
verified before products become available. This verification can take
24-48 hours after submitting your information.
</div>
<Callout kind="important">
The merchant account must be fully verified before products become
available. This verification can take 24-48 hours after submitting
your information.
</Callout>
</section>

<section>
Expand Down Expand Up @@ -323,19 +303,11 @@ dependencies {
<li>Test cards are automatically used - no real charges occur</li>
</ul>

<div
style={{
padding: '1rem',
background: 'rgba(164, 116, 101, 0.1)',
borderLeft: '4px solid var(--primary-color)',
borderRadius: '0.5rem',
margin: '1rem 0',
}}
>
<strong>💡 Tip:</strong> For faster testing during development, use
Android Debug Bridge (ADB) to clear Google Play Store cache:{' '}
<Callout kind="tip">
For faster testing during development, use Android Debug Bridge (ADB)
to clear Google Play Store cache:{' '}
<code>adb shell pm clear com.android.vending</code>
</div>
</Callout>
</section>

<section>
Expand Down Expand Up @@ -378,22 +350,9 @@ dependencies {

<p>
These libraries implement the OpenIAP specification and handle
Android-specific requirements.
Android-specific requirements — refer to each library&apos;s
documentation for implementation details.
</p>

<div
style={{
padding: '1rem',
background: 'rgba(164, 116, 101, 0.1)',
borderLeft: '4px solid var(--primary-color)',
borderRadius: '0.5rem',
margin: '1rem 0',
}}
>
<strong>💡 Note:</strong> Refer to the specific library documentation
for implementation details. Each library follows the OpenIAP
specification while handling platform-specific requirements.
</div>
</section>

<section>
Expand All @@ -412,7 +371,14 @@ dependencies {
</h3>
<p>
Android requires acknowledging purchases within 3 days. Unacknowledged
purchases are automatically refunded by Google Play.
purchases are automatically refunded by Google Play. In OpenIAP SDKs
the completion order is: verify with a trusted verifier (your backend
or <a href="/docs/kit-backend">IAPKit</a>), grant and persist the
entitlement so it survives a restart, then acknowledge through{' '}
<a href="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</a>
.
</p>

<h3 id="consumable-products" className="anchor-heading">
Expand All @@ -424,6 +390,11 @@ dependencies {
<p>
Consumable products must be consumed before they can be purchased
again. This prevents duplicate purchases of items like coins or lives.
Consumption is the{' '}
<a href="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</a>{' '}
call with <code>isConsumable: true</code>.
</p>

<h3 id="purchase-verification" className="anchor-heading">
Expand All @@ -434,8 +405,10 @@ dependencies {
</h3>
<p>
Always verify purchases through a trusted verifier that calls the
Google Play Developer API, either your backend or IAPKit, to prevent
fraud and ensure purchase validity.
Google Play Developer API — either your backend or{' '}
<a href="/docs/kit-backend">IAPKit</a> — to prevent fraud and ensure
purchase validity. See the{' '}
<a href="/docs/features/validation">Purchase Verification guide</a>.
</p>

<h3 id="billing-choice" className="anchor-heading">
Expand Down Expand Up @@ -516,20 +489,11 @@ dependencies {
<li>Renewal notifications</li>
</ul>

<div
style={{
padding: '1rem',
background: 'rgba(220, 104, 67, 0.1)',
borderLeft: '4px solid var(--accent-color)',
borderRadius: '0.5rem',
margin: '1rem 0',
}}
>
<strong>⚠️ Important:</strong> OpenIAP libraries handle these
Android-specific requirements automatically. Consult the library
documentation for your chosen framework to ensure proper
implementation.
</div>
<p>
OpenIAP libraries handle these Android-specific requirements
automatically. Consult the library documentation for your chosen
framework to ensure proper implementation.
</p>
</section>

<section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import Callout from '../../../../components/Callout';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
Expand Down Expand Up @@ -41,18 +42,16 @@ function AcknowledgePurchaseAndroid() {
.
</p>

<div className="alert-card alert-card--warning">
<p>
⚠️ <strong>Deprecated in Google Play Billing Library 8.2.0+.</strong>{' '}
Direct acknowledge / consume calls are being phased out — use the
cross-platform{' '}
<Link to="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</Link>{' '}
API instead, which handles acknowledgment automatically and is the
recommended path for new code.
</p>
</div>
<Callout kind="warning">
<strong>Deprecated in Google Play Billing Library 8.2.0+.</strong>{' '}
Direct acknowledge / consume calls are being phased out — use the
cross-platform{' '}
<Link to="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</Link>{' '}
API instead, which handles acknowledgment automatically and is the
recommended path for new code.
</Callout>

<h2>Signature</h2>
<LanguageTabs>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import Callout from '../../../../components/Callout';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
Expand Down Expand Up @@ -38,18 +39,15 @@ function ConsumePurchaseAndroid() {
.
</p>

<div className="alert-card alert-card--warning">
<p>
⚠️ <strong>Deprecated in Google Play Billing Library 8.2.0+.</strong>{' '}
Use{' '}
<Link to="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</Link>{' '}
with <code>isConsumable: true</code> instead — the unified path
consumes (or acknowledges) the purchase automatically and stays
forward-compatible with the new Billing Programs API.
</p>
</div>
<Callout kind="warning">
<strong>Deprecated in Google Play Billing Library 8.2.0+.</strong> Use{' '}
<Link to="/docs/apis/finish-transaction">
<code>finishTransaction</code>
</Link>{' '}
with <code>isConsumable: true</code> instead — the unified path consumes
(or acknowledges) the purchase automatically and stays
forward-compatible with the new Billing Programs API.
</Callout>

<h2>Signature</h2>
<LanguageTabs>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import Callout from '../../../../components/Callout';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
Expand Down Expand Up @@ -47,20 +48,17 @@ function CreateBillingProgramReportingDetailsAndroid() {
</a>
.
</p>
<div className="alert-card alert-card--warning">
<p>
<strong>External Offer ordering:</strong> check availability, create
fresh reporting details immediately before the redirect, then call{' '}
<Link to="/docs/apis/android/launch-external-link-android">
<code>launchExternalLinkAndroid()</code>
</Link>
. After checkout, send that invocation&apos;s token to your backend
and report the transaction to Google within 24 hours. Never reuse a
token from an earlier launch attempt. See the complete{' '}
<Link to="/docs/features/external-purchase">External Offer flow</Link>
.
</p>
</div>
<Callout kind="warning" title="External Offer ordering">
Check availability, create fresh reporting details immediately before
the redirect, then call{' '}
<Link to="/docs/apis/android/launch-external-link-android">
<code>launchExternalLinkAndroid()</code>
</Link>
. After checkout, send that invocation&apos;s token to your backend and
report the transaction to Google within 24 hours. Never reuse a token
from an earlier launch attempt. See the complete{' '}
<Link to="/docs/features/external-purchase">External Offer flow</Link>.
</Callout>

<h2>Signature</h2>
<LanguageTabs>
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/pages/docs/apis/fetch-products.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../components/AnchorLink';
import Callout from '../../../components/Callout';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
Expand Down Expand Up @@ -53,9 +54,8 @@ function FetchProducts() {
<AnchorLink id="request-apis" level="h2">
Note about <code>request*</code> APIs
</AnchorLink>
<div className="alert-card alert-card--info">
<Callout kind="note">
<p>
ℹ️{' '}
<strong>This note is about sibling APIs, not fetchProducts.</strong>{' '}
<code>fetchProducts</code> itself is a regular promise-based call —
its <code>Promise&lt;FetchProductsResult&gt;</code> return value{' '}
Expand Down Expand Up @@ -87,7 +87,7 @@ function FetchProducts() {
</a>
.
</p>
</div>
</Callout>

<h2>Signature</h2>
<LanguageTabs>
Expand Down
13 changes: 6 additions & 7 deletions packages/docs/src/pages/docs/apis/finish-transaction.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../components/AnchorLink';
import Callout from '../../../components/Callout';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
Expand Down Expand Up @@ -208,13 +209,11 @@ await ((MutationResolver)OpenIapClient.Instance).FinishTransactionAsync(
}}
</LanguageTabs>

<div className="alert-card alert-card--warning">
<p>
<strong>Critical:</strong> Android purchases must be acknowledged
within 3 days or they will be automatically refunded. iOS transactions
will replay on every app launch if not finished.
</p>
</div>
<Callout kind="warning" title="Critical">
Android purchases must be acknowledged within 3 days or they will be
automatically refunded. iOS transactions will replay on every app launch
if not finished.
</Callout>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import Callout from '../../../../components/Callout';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
Expand Down Expand Up @@ -37,13 +38,11 @@ function PresentExternalPurchaseLinkIOS() {
</a>
.
</p>
<div className="alert-card alert-card--info">
<p>
<strong>macOS:</strong> Not supported. The current OpenIAP Apple core
implementation uses <code>UIApplication</code> and returns a
feature-not-supported error on macOS.
</p>
</div>
<Callout kind="note" title="macOS">
Not supported. The current OpenIAP Apple core implementation uses{' '}
<code>UIApplication</code> and returns a feature-not-supported error on
macOS.
</Callout>

<h2>Signature</h2>
<LanguageTabs>
Expand Down
Loading