# How Payment QR Codes Are Generated and Displayed in biliTickerBuy: A Complete Technical Guide

> Discover how biliTickerBuy generates and displays payment QR codes using the BiliBili API and qrcode library. Get a technical deep dive into the purchase process.

- Repository: [Qizhuo Xie/biliTickerBuy](https://github.com/mikumifa/biliTickerBuy)
- Tags: internals
- Published: 2026-06-23

---

**The biliTickerBuy repository generates payment QR codes by calling the BiliBili API endpoint `/api/ticket/order/getPayParam` to retrieve a payment URL, then emits a `payment_qr` event for the UI while optionally rendering the QR image locally using the `qrcode` library.**

When a ticket purchase succeeds in the `mikumifa/biliTickerBuy` automation tool, the system must bridge the gap between BiliBili's backend payment system and the user's screen. This article examines how the codebase fetches payment parameters, generates scannable QR codes, and displays them through multiple channels according to the source implementation.

## The Payment QR Code Generation Flow

The **payment QR code** generation follows a strict pipeline from order creation to final display. Each step is handled by specific functions in the `task` module.

### Step 1: Order Creation and ID Extraction

After a successful `create` request to BiliBili's ticket API, the response contains an `orderId` field. The code extracts this identifier using `extract_order_id` to begin the payment preparation phase.

In [`main/task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy.py) around line 666, the successful order creation triggers the QR code generation sequence:

```python
if errno == 0:  # Order created successfully

    order_id = request_result["data"]["orderId"]
    payment_url = get_order_detail_url(order_id)  # Human-readable page

    qrcode_url = get_qrcode_url(_request, order_id)

```

### Step 2: Fetching the Payment URL

The `get_qrcode_url` function in [`main/task/buy_helpers.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy_helpers.py) (line 27) calls the BiliBili API endpoint `/api/ticket/order/getPayParam?order_id={order_id}`. This returns a JSON object where the `data.code_url` field contains the actual **payment QR code URL**.

```python

# task/buy_helpers.py

def get_qrcode_url(_request, order_id) -> str:
    """Call BiliBili API and return the payment QR code URL."""
    url = f"{BASE_URL}/api/ticket/order/getPayParam?order_id={order_id}"
    data = _request.get(url).json()
    if data.get("errno", data.get("code")) == 0:
        return data["data"]["code_url"]
    raise ValueError("获取二维码失败")

```

### Step 3: Emitting the Payment Event

The system yields a **`payment_qr`** event that UI components listen for. This event carries the prefix `PAYMENT_QR_URL=` followed by the payment URL, enabling Gradio tabs and other interfaces to render the QR code dynamically.

From [`main/task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy.py) (line 734):

```python
yield emit("payment_qr",
           f"PAYMENT_QR_URL={payment_url}",
           BuyStreamUpdate(payment_qr_url=payment_url,
                           status="succeeded"))

```

### Step 4: Local QR Image Rendering

When `config.show_qrcode` is enabled, the code creates a `qrcode.QRCode` object, adds the **QR-code URL** (`qrcode_url`), and displays it using the default system image viewer. This implementation spans lines 942-998 in [`main/task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy.py):

```python
if config.show_qrcode:
    qr = qrcode.QRCode()
    qr.add_data(qrcode_url)
    qr.make(fit=True)
    img = qr.make_image()
    img.show()  # Pops up the default image viewer

```

### Step 5: Automatic Browser Opening

If the user enables automatic opening, `webbrowser.open(payment_url)` launches the order detail page in the default browser. This occurs at line 780 in [`main/task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy.py), accompanied by a status message indicating the link has been opened automatically.

## Configuration Flags Controlling Display

Two boolean flags in [`main/app_cmd/config/BuyConfig.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/app_cmd/config/BuyConfig.py) govern the **payment QR code** display behavior:

- **`show_qrcode`** (default: `True`): Controls whether the local QR image viewer pops up after successful purchase. Defined at line 103.
- **`auto_open_payment_url`** (default: `False`): Determines if the system automatically opens the payment page in the default browser. Defined at line 204.

These settings are exposed to the UI layer through [`main/interface/config.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/interface/config.py) and can be toggled in [`main/tab/settings.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/tab/settings.py).

## Edge Case: Terminal Rules with Existing Orders

The system handles **unfinished orders** (such as error 100048) through terminal rules. When a terminal rule has `expose_payment_url=True`, the same QR code generation flow executes without a successful `create` result. The code extracts the existing `order_id`, builds the order-detail URL, emits the `payment_qr` event, and applies the auto-open logic.

This fallback path appears in [`main/task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy.py) (lines 713-735), ensuring users can pay for pending orders even when the initial creation fails.

## Summary

- **Payment QR acquisition**: The `get_qrcode_url` helper calls `/api/ticket/order/getPayParam` and extracts `data.code_url` from the BiliBili API response.
- **Event-driven architecture**: The system emits `payment_qr` events with `PAYMENT_QR_URL=` prefixes that UI components consume for display.
- **Local rendering**: The `qrcode` library generates images displayed via `img.show()` when `show_qrcode` is enabled.
- **Browser automation**: `webbrowser.open()` launches payment pages automatically when `auto_open_payment_url` is set to `True`.
- **Edge case handling**: Terminal rules with `expose_payment_url=True` trigger the same display flow for existing unfinished orders.

## Frequently Asked Questions

### Where does the payment QR code URL come from?

The URL originates from BiliBili's internal API endpoint `/api/ticket/order/getPayParam`. The `get_qrcode_url` function in [`main/task/buy_helpers.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy_helpers.py) makes an authenticated GET request with the `order_id` parameter and returns the `code_url` field from the JSON response.

### How can I disable the automatic QR image popup?

Set the `show_qrcode` configuration flag to `False` in your `BuyConfig`. This boolean value (defaulting to `True` in [`main/app_cmd/config/BuyConfig.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/app_cmd/config/BuyConfig.py) at line 103) controls whether `qr_gen_image.show()` executes after a successful purchase.

### What happens if there's already an unfinished order?

When the system encounters a terminal rule like error 100048 ("已有未完成订单") with `expose_payment_url=True`, it extracts the existing `order_id` and executes the same **payment QR code** display flow without creating a new order. This ensures users can complete payment for pending transactions.

### Which file handles the BiliBili API request for payment parameters?

The [`main/task/buy_helpers.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/task/buy_helpers.py) file contains the `get_qrcode_url` function that constructs the API URL and processes the response. It uses the `_request` object (typically an instance of `BiliRequest` from [`main/util/request/BiliRequest.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/main/util/request/BiliRequest.py)) to handle the actual HTTP GET request to BiliBili's servers.