kylin987/netsale-report-sdk

PHP SDK for cinema netsale box-office reporting (2025 protocol)

Maintainers

Package info

github.com/kylin987/netsale-report-sdk

pkg:composer/kylin987/netsale-report-sdk

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-06-30 03:43 UTC

This package is auto-updated.

Last update: 2026-06-30 06:25:30 UTC


README

网售票房上报 SDK(2025 协议)— 用于专资办正式票房上报,包含售票 / 退票上报和数据比对文件下载。

功能

方法 说明
reportTicket 票房数据上报(售票 operation=1 / 退票 operation=2),一次最多 50 条
downloadReportRecord 数据比对文件下载(需 V-STK p7AttachSign 签名),返回 zip 文件流

环境要求

  • PHP >= 8.1
  • ext-openssl
  • ext-curl
  • V-STK 签名服务(downloadReportRecord 需要,通过 VstkSignerInterface 接入)

安装

composer require kylin987/netsale-report-sdk

快速开始

<?php

use NetsaleReportSdk\Config;
use NetsaleReportSdk\Model\ReportTicket;
use NetsaleReportSdk\NetsaleReportClient;

// --- 配置 ---
$config = new Config([
    'reportUrl'   => 'https://your-host/report/report',
    'serviceUrl'  => 'https://your-host/service',
    'channelCode' => 'your-channel-code',
    'certId'      => 'your-cert-id',
    'certFile'    => '/path/to/client_cert.pem',
    'keyFile'     => '/path/to/client_key.pem',
    'trustFile'   => '/path/to/rootcert.pem',
    'vstkSigner'  => new HttpVstkSigner('http://127.0.0.1:18080/sign'),
]);

$client = new NetsaleReportClient($config);

// --- 售票上报 ---
$ticket = new ReportTicket();
$ticket->numberByDay        = 1;
$ticket->parentChannelCode  = '13090401';
$ticket->childChannelCode   = '00000000';
$ticket->ticketNo           = '130904010Ba0102';
$ticket->cinemaCode         = '13090401';
$ticket->screenCode         = '0000000000000001';
$ticket->seatCode           = '88888888010010011101';
$ticket->filmCode           = '000000252022';
$ticket->sessionCode        = 'SE00001234567890';
$ticket->sessionDatetime    = '2026-03-31 21:20:00';
$ticket->ticketPrice        = 56.00;
$ticket->screenServiceFee   = 0.00;
$ticket->netServiceFee      = 8.00;
$ticket->saleChannelCode     = 'your-channel-code';
$ticket->operation          = 1;  // 1=售票, 2=退票
$ticket->operationDatetime  = '2026-03-31 21:20:00';

$result = $client->reportTicket([$ticket]);

if ($result->isSuccess()) {
    echo '上报成功, traceId: ' . $result->traceId . PHP_EOL;
} else {
    echo '上报失败: ' . $result->code . ' ' . $result->status . PHP_EOL;
}

// --- 退票上报(operation 改为 2) ---
$ticket->operation         = 2;
$ticket->operationDatetime = date('Y-m-d H:i:s');
$client->reportTicket([$ticket]);

// --- 数据比对文件下载 ---
$zipContent = $client->downloadReportRecord('2026-03-01', '2026-03-31');
file_put_contents('report_record.zip', $zipContent);

配置参数

参数 类型 必填 说明
reportUrl string 上报接口地址(SDK 自动追加 /reportTicket
serviceUrl string 下载接口地址(SDK 自动追加 /data/downloadReportRecord
channelCode string 网售商编码(sendChannelCode)
certId string 证书 ID(通常等于 channelCode,V-STK 签名时使用)
certFile string 客户端证书路径(PEM 格式)
keyFile string 客户端私钥路径(PEM 格式,与证书分离)
keyFilePwd string 私钥密码(PEM 加密时使用,通常为空)
trustFile string 信任根证书路径(CA 链 PEM)
proxy string 代理地址(不填时默认禁用系统代理)
vstkSigner object 下载时必填 V-STK 签名器,需实现 VstkSignerInterface
httpLogger callable HTTP 日志回调,接收 array 上下文
reportToken string 业务层上报令牌(SDK 不使用,供业务层读取)

V-STK 签名器

downloadReportRecord 需要调用 V-STK 的 p7AttachSign 方法进行签名。PHP 无法直接调用 V-STK COM 组件,通过 VstkSignerInterface 接入外部签名服务。

接口定义

interface VstkSignerInterface
{
    /**
     * @param string $certId    证书标识(通常为网售商编码)
     * @param string $plainText 签名原文(JSON 字符串)
     * @return string           V-STK 返回的 Base64 签名字符串
     */
    public function p7AttachSign(string $certId, string $plainText): string;
}

HTTP 签名桥实现示例

<?php

use NetsaleReportSdk\Signer\VstkSignerInterface;

class HttpVstkSigner implements VstkSignerInterface
{
    public function __construct(private string $url) {}

    public function p7AttachSign(string $certId, string $plainText): string
    {
        $ch = curl_init($this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'certId'    => $certId,
            'plainText' => $plainText,
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);

        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            throw new RuntimeException('V-STK signer error: ' . curl_error($ch));
        }

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($httpCode >= 400) {
            throw new RuntimeException("V-STK signer HTTP {$httpCode}: {$response}");
        }

        $decoded = json_decode((string) $response, true);
        if (is_array($decoded) && ($decoded['ok'] ?? false) === true) {
            return (string) ($decoded['signData'] ?? '');
        }

        return trim((string) $response);
    }
}

V-STK 签名桥配置要点

  • SM2 证书需设置 DigestAlg=SM3EncAlg=SM4asymmalg=SM2
  • SSL 协议需 TLSv1.2
  • PHP 端通过 HTTP 调用 Java 签名桥(如 cn.com.jit.new_vstk.AdvanceSignClient.p7AttachSign

与 2025 协议的差异

与旧 zzb-sdk-php 的 netsale2025 模式相比:

  • reportTicket 根级直接发送 sendChannelCode + ticketList,不加业务签名
  • downloadReportRecord 需要 V-STK p7AttachSign 签名
  • 证书只支持 PEM 格式(证书 + 私钥分离),不再处理 PFX/P12

联调脚本

包内附带冒烟测试脚本:

# dry-run(不实际请求)
php examples/smoke.php

# 真实上报
php examples/smoke.php --send-report --confirm-submit-test-data

# 下载比对文件(需 V-STK 签名桥)
php examples/smoke.php --download-record --vstk-signer-url=http://127.0.0.1:18080/sign

环境变量参见脚本头部注释。

数据模型

模型 说明
ReportTicket 上报票据(numberByDay, ticketNo, cinemaCode, operation 等 16 个字段)
ReportResult 上报响应(code, status, data, traceId),isSuccess() 判断是否 code === '200'

版本

版本 说明
v1.0.0 从 zzb-sdk-php 2.x 提取 netsale2025 逻辑,独立发布

License

MIT