# Selling software, subscriptions and in-app purchases

Set a product's type, billing period and its own price on the web, the App Store and Google Play, then bring each customer's plans and purchases onto their profile, from the stores or from your own system, so agents and the AI assistant answer right.

If you sell an app or software, one plan often has three prices: on the web, on the App Store and on Google Play, each store with its own product id. Ha Tang keeps all three on one product: customers writing from your iOS app see the App Store price, from your Android app the Google Play price, on the web the web price. Each customer's plans (active, trial, won't renew, expired, refunded) and one-time purchases then show on their profile.

There are two ways to bring purchases into Ha Tang, and you can use both:

- **Connect the App Store and Google Play.** Ha Tang checks each purchase with Apple or Google and receives every renewal, cancellation and refund from the stores. Your app passes the customer's account token when buying. Suits apps whose own servers do not check store purchases yet.
- **Send them from your own system.** Your server, which already checks purchases with the stores or takes payments on your website, sends each plan and purchase to Ha Tang. Nothing to connect in the stores. Suits apps that already have a backend for in-app purchases, and anything you sell on the web.

The same purchase sent both ways stays one record.

You need **Work** access to Products to edit products, and **Manage** access to Customer Support to connect the stores.

## Create a subscription

1. Go to **Products → Catalog** and click **Add product** (or open an existing one).
2. Under **Type**, choose:
   - **Subscription** for a plan paid per period; then pick the **Billing period** (weekly, monthly, every 3 or 6 months, yearly) and **Free trial (days)** if any;
   - **In-app purchase, consumable** for something used up and bought again (coins, credits);
   - **In-app purchase, one-time** for something bought once and kept (unlocking a feature);
   - **Digital product** for software sold once on the web.
3. **Web price (₫)** and the **Product page URL** are the price and checkout page for customers on the web.
4. Open **Prices on the App Store and Google Play** and fill in each store:
   - the **product ID** you created in App Store Connect or the Play Console;
   - the **Price** and **Currency** you set in that store, for example `4.99` `USD` on the App Store and `219000` `VND` on Google Play;
   - for a Google Play subscription: the **Base plan ID**, and the **Offer ID** if there is an offer such as a free trial.
5. If a variant has its own ids (a yearly plan, say), add it under **Prices per variant**, one per line: `ios | Yearly | 49.99 | USD | com.app.pro.yearly`.
6. Fill in **SKU** with your own code for the plan (for example `PRO-1M`). Purchases your system sends, above all those made on your website where there is no store product id, find their product by this SKU, so the customer's profile shows the plan's name.
7. Click **Save**.

Import many plans at once from a CSV file with the columns `kind`, `billing_period`, `trial_days`, `ios_product_id`, `ios_price`, `ios_currency`, `android_product_id`, `android_price`, `android_currency`, `android_base_plan_id` (see [Your product catalog](https://hatang.dev/help/products/product-catalog)).

## What customers and the AI assistant see

- **Product cards** sent to a customer carry the price on the platform they are using, with the billing period and free trial. Inside your app a card carries only that store's id, so **Buy** starts Apple's or Google's purchase; on the web it carries the checkout page.
- **The AI assistant** quotes the platform's price ("$4.99/month on the App Store, 7-day free trial"). For in-app products it never offers a bank transfer or a draft order, since Apple and Google require their own checkout.
- Cards an agent sends from the reply box (**Product**) are priced for the customer's platform too.

## Connect the App Store and Google Play

Connect so every purchase, renewal, cancellation and refund from the stores reaches Ha Tang. Your developers add one step in the app: pass the customer's account token when buying (see the [SDK guides](https://hatang.dev/docs/guides/sdks/compatibility)), so each transaction lands on the right customer.

If your own server already receives the stores' notifications, you do not need this section: Apple allows one notification URL per environment, so keep it on your server and [send purchases from your own system](#send-plans-and-purchases-from-your-own-system) instead.

### App Store

1. Go to **Customer Support → Channels** and open your iOS app.
2. Under **Subscriptions from the App Store and Google Play**, enter the app's **Bundle ID** and click **Connect**.
3. Copy the **Notification URL**.
4. In App Store Connect, open the app → **App Information → App Store Server Notifications**, paste the URL for **Production** and **Sandbox**, and choose **Version 2**.
5. Click **Request a Test Notification**. The app page in Ha Tang shows "Last notification" with the time.

**App Store Server API key (optional).** With this key Ha Tang can ask Apple at any time instead of only waiting for notifications: the **Refresh** link on each plan, a daily check of plans due to renew (in case a notification got lost), and importing customers who bought before you connected.

1. In App Store Connect → **Users and Access → Integrations → In-App Purchase**, generate a key. Note the **Issuer ID** and **Key ID** and download the `.p8` file (Apple lets you download it only once).
2. In Ha Tang, open **App Store Server API key** in the same card, enter both ids, choose the `.p8` file and click **Save**.

### Google Play

1. In Google Cloud, create a service account, then in Play Console → **Users and permissions** invite its email with **View financial data** and **Manage orders and subscriptions** (so Ha Tang can acknowledge purchases with Google). Download the service account's JSON key.
2. In Ha Tang, open your Android app under **Channels**, enter the **Package name**, upload the JSON key and click **Connect**.
3. Copy the **Push URL**.
4. In Google Cloud, create a Pub/Sub topic, grant **Publisher** to `google-play-developer-notifications@system.gserviceaccount.com`, and add a **Push** subscription with the URL you copied.
5. In Play Console → **Monetization setup**, enter the topic and click **Send test notification**.

If a notification is refused (wrong bundle ID or package, a key without access), the app page shows **Last error** with the reason.

## The customer's plans on their profile

**Plans** shows in the conversation's side panel and on the customer page: the plan, the store, the status and the renewal or end date.

| Status | Means |
|---|---|
| **Trial** | In the free trial |
| **Active** | Paid, renews automatically |
| **Grace period** | The last payment failed and the store is retrying; the customer keeps access |
| **On hold (payment failed)** | The store stopped access until the customer fixes their payment method |
| **Paused** | The customer paused the plan (Google Play) |
| **Won't renew** | The customer canceled; access lasts until the period ends |
| **Expired** | The last period ended |
| **Refunded** / **Revoked** | The store refunded or revoked the transaction |

The AI assistant reads this too, so it can answer "which plan am I on?" and "when does it renew?". For App Store and Google Play plans it sends customers to Apple or Google for refunds and payment methods, and never promises a refund.

When the stores are connected, right after each purchase the app sends the store's proof of the transaction (SDK `reportPurchase`). Ha Tang checks it with Apple or Google before recording the plan; fake transactions are refused. For Google Play, Ha Tang also acknowledges the purchase, so Google does not refund it automatically after three days. The open conversation also gets an internal note.

Customers who buy before signing in to the app keep their plan: when the app identifies them, the purchases made on that phone move to their profile.

### One-time purchases

One-time purchases (coin packs, lifetime unlocks, non-renewing plans, courses) show under the plans, with their type (**Consumable**, **One-time purchase**, **Non-renewing plan**), where they were bought (**App Store**, **Google Play** or **Web**) and the purchase date. A refund from the store or from your own system shows **Refunded**.

### Refresh and import existing customers

- **Refresh** next to an App Store or Google Play plan asks the store again right away. It works only when the stores are connected, and needs the App Store Server API key (iOS) or the service account (Android).
- To import customers who bought before you connected, your developers send Apple transaction ids or Google Play purchase tokens through the API (`POST /chat/subscriptions/import`, up to 500 per call).

## Send plans and purchases from your own system

Your developers send Ha Tang what your system already knows, right after each change: a purchase, a renewal, an expiry, a refund. This covers:

- **Plans paid on your website** (bank transfer, your own payment provider);
- **App Store and Google Play plans and purchases** that your server already checks with Apple or Google;
- **One-time purchases**: coin packs, unlocks, courses, on the web or in the stores, and their refunds.

How it works:

- Each record carries the **user id** your app and website use to identify the customer in the chat, so it lands on their profile. Records for someone who has never opened the chat appear as soon as they do.
- Plans and purchases find their product by its **SKU** or its App Store / Google Play product id, so set those on your products.
- Sending the same plan or purchase again only updates it, so your system can resend everything after each change, and send the history once to fill in customers who bought before.
- Your developers use the Node.js SDK (`@hatang/sdk` 0.6.0 or later), the Python SDK (`hatang`) or the REST API with an API key that has the CRM write scope. See [Send purchases from your backend](https://hatang.dev/docs/guides/support/in-app-purchases#backend), the [Node.js SDK](https://hatang.dev/docs/guides/sdks/node) and the [Python SDK](https://hatang.dev/docs/guides/sdks/python).
