kemo/beatport-api-client 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kemo/beatport-api-client

Composer 安装命令:

composer require kemo/beatport-api-client

包简介

Standalone Beatport API client for PHP

README 文档

README

CI codecov PHPStan level 6 PHP 8.4+ License: MIT

A standalone PHP client for the Beatport API. Provides three complementary clients for different access patterns: OAuth API, internal API, and web scraping.

Features

  • OAuth API client — Authenticated access to Beatport API v4 (library, tracks, search)
  • Internal API client — Public access to tracks, artists, labels, releases, genres, and charts
  • Scrape client — Session-based web scraping for library and track data
  • Full auth flow — OAuth PKCE authorization and username/password login
  • DTOs — Structured BeatportTrack and LoginResult objects
  • Domain exceptionsAuthenticationException, InvalidSessionException, SessionExpiredException

Installation

composer require kemo/beatport-api-client

Requires PHP 8.4+ and a PSR-18 compatible HTTP client. The package uses symfony/http-client-contracts, so any Symfony HTTP client implementation works:

composer require symfony/http-client

Usage

Internal API Client (No Auth Required)

The InternalApiClient accesses Beatport's internal API without authentication:

use Kemo\Beatport\InternalApiClient;
use Symfony\Component\HttpClient\HttpClient;

$client = new InternalApiClient(HttpClient::create());

// Tracks
$track = $client->getTrack(123456);
$tracks = $client->getTracks(page: 1, perPage: 25, orderBy: '-publish_date');
$topTracks = $client->getTopTracks(genreId: 1, page: 1, perPage: 100);

// Artists
$artist = $client->getArtist(12345);
$artistTracks = $client->getArtistTopTracks(artistId: 12345, perPage: 10);

// Labels
$label = $client->getLabel(678);
$labelTracks = $client->getLabelTopTracks(labelId: 678, perPage: 10);

// Releases
$release = $client->getRelease(789);

// Genres
$genres = $client->getGenres();
$genre = $client->getGenre(1);
$genreTracks = $client->getGenreTopTracks(genreId: 1, perPage: 10);

// Charts
$chart = $client->getChart(456);
$charts = $client->getCharts(page: 1, perPage: 25);

// Search
$results = $client->search(query: 'Daft Punk', type: 'tracks', page: 1, perPage: 25);

OAuth API Client

The ApiClient requires an OAuth access token:

use Kemo\Beatport\ApiClient;
use Symfony\Component\HttpClient\HttpClient;

$client = new ApiClient(HttpClient::create(), accessToken: 'your-access-token');

$account = $client->getAccount();
$myTracks = $client->getMyBeatportTracks(perPage: 100);
$track = $client->getTrack(123456);
$results = $client->searchTracks(query: 'Bicep', page: 1, perPage: 25);
$topTracks = $client->getTopTracks(page: 1, perPage: 25);

Authentication

OAuth PKCE Flow

use Kemo\Beatport\AuthClient;
use Symfony\Component\HttpClient\HttpClient;

$auth = new AuthClient(HttpClient::create());

// Step 1: Get authorization URL
$url = $auth->getAuthorizationUrl(
    clientId: 'your-client-id',
    redirectUri: 'https://your-app.com/callback',
    codeChallenge: $challenge,
);

// Step 2: Exchange code for tokens
$tokens = $auth->exchangeCodeForTokens(
    clientId: 'your-client-id',
    redirectUri: 'https://your-app.com/callback',
    code: $authorizationCode,
    codeVerifier: $verifier,
);
// $tokens = ['access_token' => '...', 'refresh_token' => '...', 'expires_in' => 3600]

// Step 3: Refresh when expired
$refreshed = $auth->refreshAccessToken(
    clientId: 'your-client-id',
    refreshToken: $tokens['refresh_token'],
);

Username/Password Login

use Kemo\Beatport\LoginClient;
use Kemo\Beatport\AuthClient;
use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();
$login = new LoginClient($httpClient, new AuthClient($httpClient));

$result = $login->login(username: 'user@example.com', password: 'password');
// LoginResult with: sessionCookies, username, accessToken, refreshToken, expiresIn, beatportUserId

Scrape Client

The ScrapeClient uses session cookies for web scraping:

use Kemo\Beatport\ScrapeClient;
use Symfony\Component\HttpClient\HttpClient;

$scraper = new ScrapeClient(HttpClient::create(), requestDelayUs: 500_000);
$scraper->setSession($sessionCookies);

if ($scraper->isSessionValid()) {
    $tracks = $scraper->getLibraryTracks(page: 1);
    $allTracks = $scraper->getAllLibraryTracks(maxPages: 50);
    $pageCount = $scraper->getLibraryPageCount(maxPages: 50);
    $track = $scraper->getTrack(trackId: 123456, slug: 'track-name');
    $results = $scraper->searchTracks(query: 'Disclosure', page: 1);
}

DTOs

BeatportTrack

use Kemo\Beatport\Dto\BeatportTrack;

// From API response
$track = BeatportTrack::fromApiResponse($apiData);

// From scraped data
$track = BeatportTrack::fromScrapedData($scrapedData);

$track->beatportId;  // string
$track->title;       // string
$track->mix;         // ?string
$track->artistName;  // ?string
$track->albumName;   // ?string
$track->durationMs;  // ?int
$track->bpm;         // ?int
$track->musicalKey;  // ?string
$track->genre;       // ?string
$track->label;       // ?string

Exception Handling

use Kemo\Beatport\Exception\AuthenticationException;
use Kemo\Beatport\Exception\InvalidSessionException;
use Kemo\Beatport\Exception\SessionExpiredException;

try {
    $login->login('user@example.com', 'wrong-password');
} catch (AuthenticationException $e) {
    // Authentication failed
}

try {
    $scraper->setSession('invalid-cookies');
} catch (InvalidSessionException $e) {
    // Invalid session cookies
}

try {
    $scraper->getLibraryTracks();
} catch (SessionExpiredException $e) {
    // Session has expired
}

Architecture

src/
├── AbstractApiClient.php      # Shared HTTP client base class
├── ApiClient.php              # OAuth API v4 client
├── InternalApiClient.php      # Internal API client (no auth)
├── ScrapeClient.php           # Web scraping client
├── AuthClient.php             # OAuth PKCE flow
├── LoginClient.php            # Username/password login
├── Beatport.php               # URL constants
├── Dto/
│   ├── BeatportTrack.php      # Track data transfer object
│   ├── LoginResult.php        # Login result DTO
│   └── TrackTitleParser.php   # Title/mix parser utility
├── Exception/
│   ├── AuthenticationException.php
│   ├── InvalidSessionException.php
│   └── SessionExpiredException.php
└── Util/
    └── SlugHelper.php         # URL slug generation

Development

# Install dependencies
composer install

# Run tests
composer test

# Run tests with coverage
composer test:coverage

# Static analysis
composer phpstan

# Check code style
composer cs:check

# Fix code style
composer cs:fix

# Full QA pipeline (cs:check + phpstan + test)
composer qa

License

MIT. See LICENSE.

Contributing

See CONTRIBUTING.md.

Changelog

See CHANGELOG.md.

kemo/beatport-api-client 适用场景与选型建议

kemo/beatport-api-client 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 12 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「api」 「client」 「scraper」 「music」 「beatport」 「dj」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 kemo/beatport-api-client 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 kemo/beatport-api-client 我们能提供哪些服务?
定制开发 / 二次开发

基于 kemo/beatport-api-client 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 26
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-12