You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中用CURL向PandaDoc API发送Base64文件及JSON遇错求助

问题描述

我尝试通过PandaDoc的「从文件创建文档」API,使用PHP的CURL发送文件,同时需在multipart/form-data中包含含收件人等信息的JSON数据。但我无法正确配置该调用,持续收到API返回的错误信息(如“There is field called file”)。以下是我的现有代码:

public function createDocument()
{
    $p = getmypid();
    $m = "({$p}): PandaDoc::create document: ";

    $postfields         = array();
    $postfields['name'] = $this->document->name;
    $postfields['file']  = $this->document->file; //base 64 encoded PDF

    $recipients = array(
        array(
            'email'      => 'a.mcdoogle@test.com',
            'first_name' => 'Andrew',
            'last_name'  => 'Mcdoogle',
            'role'       => 'user',
            'signing_order' => 1
        )
    );

    $data = array();
    $data['recipients'] = $recipients;

    $owner = array(
        "email" => "john@example.com"
    );

    $data['owner'] = $owner;

    $postfields['data'] =  json_encode($data);

    $header = array("Authorization: API-Key {$this->api_key}", "Content-Type: multipart/form-data", "accept" => "application/json");

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_URL, $this->url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

    $res = curl_exec($ch);

    if ($res === false) {
        $errno = curl_errno($ch);
        $error = curl_error($ch);
        error_log("{$m}cURL error: {$error} ({$errno})");
        throw new Exception("{$m}cURL error: {$error} ({$errno})");
    }

    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close ($ch);

    error_log("{$m}Results from PandaDoc: {$res}");

    $response = json_decode($res);

    return $response;
}

请问我哪里出错了?


问题分析与修复方案

你的代码存在三个关键问题:

  • 文件字段格式错误
    PandaDoc的multipart/form-data请求中,file字段需要传递原始文件二进制内容或文件资源句柄,而非Base64编码字符串。你需要将Base64编码的内容解码为原始二进制数据。

  • 手动指定Content-Type导致解析失败
    PHP CURL发送multipart/form-data请求时,会自动生成包含边界标识的正确Content-Type头。手动设置该头会覆盖自动生成的内容,导致API无法正确识别表单字段。

  • SSL验证被关闭(非直接错误但有安全风险)
    代码中关闭了SSL证书验证,这会带来安全隐患,建议恢复默认验证逻辑。

修正后的代码

public function createDocument()
{
    $p = getmypid();
    $m = "({$p}): PandaDoc::create document: ";

    $postfields         = array();
    $postfields['name'] = $this->document->name;
    // 将Base64编码的PDF解码为原始二进制数据
    $postfields['file'] = base64_decode($this->document->file);

    $recipients = array(
        array(
            'email'         => 'a.mcdoogle@test.com',
            'first_name'    => 'Andrew',
            'last_name'     => 'Mcdoogle',
            'role'          => 'user',
            'signing_order' => 1
        )
    );

    $data = array(
        'recipients' => $recipients,
        'owner'      => array("email" => "john@example.com")
    );

    $postfields['data'] = json_encode($data);

    // 移除手动设置的Content-Type,保留授权和Accept头
    $header = array(
        "Authorization: API-Key {$this->api_key}",
        "accept: application/json"
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    // 恢复SSL验证,提升安全性
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_URL, $this->url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

    $res = curl_exec($ch);

    if ($res === false) {
        $errno = curl_errno($ch);
        $error = curl_error($ch);
        error_log("{$m}cURL error: {$error} ({$errno})");
        throw new Exception("{$m}cURL error: {$error} ({$errno})");
    }

    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close ($ch);

    error_log("{$m}Results from PandaDoc: {$res}");

    $response = json_decode($res);

    return $response;
}

额外优化建议

如果你的$this->document->file是本地文件路径而非Base64字符串,推荐使用CURLFile类传递文件,这是PHP处理表单文件上传的标准方式:

$postfields['file'] = new CURLFile($this->document->file);

内容的提问来源于stack exchange,提问作者user794846

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:31:02