alexfantom/vonage-client-core

使用Vonage API的PHP客户端。

2.9.2 2021-04-30 21:41 UTC

README

Contributor Covenant Build Status Latest Stable Version MIT licensed codecov

Nexmo is now known as Vonage

此库需要最低PHP版本7.2

这是使用Vonage API的PHP客户端库。要使用它,您需要一个Vonage账户。在nexmo.com免费注册

安装

要使用客户端库,您需要先创建一个Vonage账户

要将PHP客户端库安装到您的项目中,我们建议使用Composer

composer require vonage/client

您不需要克隆此存储库即可在您的项目中使用此库。使用Composer从Packagist安装它。

如果您是Composer的新手,以下是一些可能有用的资源

用法

如果您使用Composer,请确保自动加载器已包含在项目引导文件中

require_once "vendor/autoload.php";

使用您的API密钥和密钥创建一个客户端

$client = new Vonage\Client(new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));     

出于测试目的,您可能想将vonage/client请求的URL从api.nexmo.com更改为其他地址。您可以在创建Vonage\Client实例时提供包含base_api_url的数组作为第二个参数来实现这一点。

$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
    [
        'base_api_url' => 'https://example.com'
    ]
);

对于通常击中rest.nexmo.com的API,将base_rest_url作为选项提供给构造函数将更改这些请求。

示例

发送消息

要使用Vonage的SMS API发送短信,调用$client->sms()->send()方法。

消息对象用于创建短信。每种消息类型都可以使用所需的参数构建,并且流畅的接口提供了对可选参数的访问。

$text = new \Vonage\SMS\Message\SMS(VONAGE_TO, VONAGE_FROM, 'Test message using PHP client library');
$text->setClientRef('test-message');

将消息对象传递给send方法

$response = $client->sms()->send($text);

发送后,可以使用消息对象来访问响应数据。

$data = $response->current();
echo "Sent message to " . $data->getTo() . ". Balance is now " . $data->getRemainingBalance() . PHP_EOL;

由于每个短信都可以分割成多个短信,响应包含每个生成的消息的对象。您可以使用PHP中的标准count()函数来检查生成了多少条消息。如果您想获取第一条消息,可以使用响应的current()方法。

$data = $response->current();
$data->getRemainingBalance();
foreach($response as $index => $data){
    $data->getRemainingBalance();
}

send示例还包含完整的工作示例。

接收消息

入站消息以webhook的形式发送到您的应用程序,客户端库提供了一种从webhook创建入站消息对象的方法

try {
    $inbound = \Vonage\SMS\Webhook\Factory::createFromGlobals();
    error_log($inbound->getText());
} catch (\InvalidArgumentException $e) {
    error_log('invalid message');
}

签名消息

您还可以阅读有关消息签名的文档

短信API支持通过使用“签名密钥”生成并添加签名来对消息进行签名,而不是使用API密钥。支持以下算法:

  • md5hash1
  • md5
  • sha1
  • sha256
  • sha512

您的应用程序和Vonage需要同意使用哪种算法。在仪表板中,访问您的账户设置页面,在“API设置”下,您可以选择要使用的算法。这也是您找到“签名密钥”的地方(它与API密钥不同)。

使用这些凭证和要使用的算法创建一个客户端,例如:

$client = new Vonage\Client(new Vonage\Client\Credentials\SignatureSecret(API_KEY, SIGNATURE_SECRET, 'sha256'));

使用此客户端,您的短信API消息将作为已签名的消息发送。

验证传入消息的签名

您还可以阅读有关消息签名的文档

如果您启用了传入消息的消息签名,则短信webhook将包括signoncetimestamp字段。要验证签名是否来自Vonage,您可以使用传入数据、签名密钥和签名方法创建一个签名对象。然后使用check()方法与实际收到的签名(通常是_GET['sig'])来确保它是正确的。

$signature = new \Vonage\Client\Signature($_GET, SIGNATURE_SECRET, 'sha256');

// is it valid? Will be true or false
$isValid = $signature->check($_GET['sig']);

使用您的签名密钥和其他提供的参数,可以计算并检查签名与传入签名值是否匹配。

开始验证

Vonage的验证API使您能够轻松证明用户在注册时提供了自己的电话号码,或在登录时实施第二因素身份验证。

您可以使用如下代码开始验证过程:

$request = new \Vonage\Verify\Request('14845551212', 'My App');
$response = $client->verify()->start($request);
echo "Started verification with an id of: " . $response->getRequestId();

用户输入他们收到的PIN码后,调用/check端点,传入请求ID和PIN,以确认PIN是正确的。

控制验证

要取消正在进行的验证或触发发送确认码的下一次尝试,您可以传递现有的验证对象到客户端库,或简单地使用请求ID。

$client->verify()->trigger('00e6c3377e5348cdaf567e1417c707a5');
$client->verify()->cancel('00e6c3377e5348cdaf567e1417c707a5');

检查验证

同样,检查验证需要用户提供的代码和请求ID。

try {
    $client->verify()->check('00e6c3377e5348cdaf567e1417c707a5', '1234');
    echo "Verification was successful (status: " . $verification->getStatus() . ")\n";
} catch (Exception $e) {
    echo "Verification failed with status " . $e->getCode()
        . " and error text \"" . $e->getMessage() . "\"\n";
}

搜索验证

您可以使用请求ID检查验证的状态或访问过去验证的结果。验证对象将提供丰富的接口。

$client->verify()->search('00e6c3377e5348cdaf567e1417c707a5');

echo "Codes checked for verification: " . $verification->getRequestId() . PHP_EOL;
foreach($verification->getChecks() as $check){
    echo $check->getDate()->format('d-m-y') . ' ' . $check->getStatus() . PHP_EOL;
}

支付验证

Vonage的验证API支持SCA(安全客户身份验证),这是PSD2(支付服务指令)要求的,并且被需要从客户那里获得支付确认的应用程序所使用。它在消息中包含收款人和金额。

像这样开始支付验证:

$request = new \Vonage\Verify\RequestPSD2('14845551212', 'My App');
$response = $client->verify()->requestPSD2($request);
echo "Started verification with an id of: " . $response['request_id'];

用户输入他们收到的PIN码后,调用/check端点,传入请求ID和PIN,以确认PIN是正确的。

发起通话

所有$client->voice()方法都需要使用Vonage\Client\Credentials\Keypair或包含Keypair凭证的Vonage\Client\Credentials\Container构建客户端。

$basic  = new \Vonage\Client\Credentials\Basic('key', 'secret');
$keypair = new \Vonage\Client\Credentials\Keypair(
    file_get_contents(VONAGE_APPLICATION_PRIVATE_KEY_PATH),
    VONAGE_APPLICATION_ID
);

$client = new \Vonage\Client(new \Vonage\Client\Credentials\Container($basic, $keypair));

您可以使用OutboundCall对象开始通话。

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);
$outboundCall
    ->setAnswerWebhook(
        new \Vonage\Voice\Webhook('https://example.com/answer')
    )
    ->setEventWebhook(
        new \Vonage\Voice\Webhook('https://example.com/event')
    )
;

$response = $client->voice()->createOutboundCall($outboundCall);

使用NCCO动作构建通话

语音API文档中可以找到NCCO动作的完整参数列表。

以下每个示例都使用以下结构向通话添加动作:

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);
$ncco = new NCCO();

//ADD ACTIONS TO THE NCCO OBJECT HERE

$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

记录通话

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(\Vonage\Voice\NCCO\Action\Record::factory([
    'eventUrl' => 'https://webhook.url'
]);
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

您的webhook URL将接收如下负载:

{
  "start_time": "2020-10-29T14:30:24Z",
  "recording_url": "https://api.nexmo.com/v1/files/<recording-id>",
  "size": 27918,
  "recording_uuid": "<recording-id>",
  "end_time": "2020-10-29T14:30:31Z",
  "conversation_uuid": "<conversation-id>",
  "timestamp": "2020-10-29T14:30:31.619Z"
}

然后您可以像这样检索并存储录音:

$recordingId = '<recording-id>';
$recordingUrl = 'https://api.nexmo.com/v1/files/' . $recordingId;
$data = $client->get($recordingUrl);
file_put_contents($recordingId.'.mp3', $data->getBody());

向语音通话发送短信

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Talk('This is a text to speech call from Vonage'));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

在通话中流式传输音频文件

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Stream('https://my-mp3.url'));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

从通话中收集用户输入

支持按键输入以及语音输入。注意:输入动作必须跟在一个将bargeIn设置为true的动作之后。

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();

$ncco->addAction(\Vonage\Voice\NCCO\Action\Talk::factory('Please record your name.',[
  'bargeIn' => true,
]));

$ncco->addAction(\Vonage\Voice\NCCO\Action\Input::factory([
  'eventUrl' => 'https://webhook.url',
  'type' => [
    'speech',
  ],
  'speech' => [
    'endOnSilence' => true,
  ],
]));

$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

webhook URL 将接收包含用户输入及其语音输入相对置信度评分的有效负载。

向 webhook URL 发送通知

$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();    
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Talk('We are just testing the notify function, you do not need to do anything.'));
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Notify([
  'foo' => 'bar',
], new Vonage\Voice\Webhook('https://webhook.url')));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);

webhook URL 将接收请求中指定的有效负载。

获取通话

您可以使用 Vonage\Call\Call 对象或作为字符串的通话 UUID 来获取通话。

$call = $client->voice()->get('3fd4d839-493e-4485-b2a5-ace527aacff3');

echo $call->getDirection();

您还可以使用过滤器搜索通话。

$filter = new \Vonage\Voice\Filter\VoiceFilter();
$filter->setStatus('completed');
foreach($client->search($filter) as $call){
    echo $call->getDirection();
}

创建应用程序

应用程序是配置容器。您可以使用简单的数组结构创建一个。

$application = new \Vonage\Application\Application();
$application->fromArray([
 'name' => 'test application',
 'keys' => [
     'public_key' => '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCA\nKOxjsU4pf/sMFi9N0jqcSLcjxu33G\nd/vynKnlw9SENi+UZR44GdjGdmfm1\ntL1eA7IBh2HNnkYXnAwYzKJoa4eO3\n0kYWekeIZawIwe/g9faFgkev+1xsO\nOUNhPx2LhuLmgwWSRS4L5W851Xe3f\nUQIDAQAB\n-----END PUBLIC KEY-----\n'
 ],
 'capabilities' => [
     'voice' => [
         'webhooks' => [
             'answer_url' => [
                 'address' => 'https://example.com/answer',
                 'http_method' => 'GET',
             ],
             'event_url' => [
                 'address' => 'https://example.com/event',
                 'http_method' => 'POST',
             ],
         ]
     ],
     'messages' => [
         'webhooks' => [
             'inbound_url' => [
                 'address' => 'https://example.com/inbound',
                 'http_method' => 'POST'

             ],
             'status_url' => [
                 'address' => 'https://example.com/status',
                 'http_method' => 'POST'
             ]
         ]
     ],
     'rtc' => [
         'webhooks' => [
             'event_url' => [
                 'address' => 'https://example.com/event',
                 'http_method' => 'POST',
             ],
         ]
     ],
     'vbc' => []
 ]
]);

$client->applications()->create($application);

您还可以向客户端传递应用程序对象。

$a = new Vonage\Application\Application;

$a->setName('PHP Client Example');
$a->getVoiceConfig()->setWebhook('answer_url', 'https://example.com/answer', 'GET');
$a->getVoiceConfig()->setWebhook('event_url', 'https://example.com/event', 'POST');
$a->getMessagesConfig()->setWebhook('status_url', 'https://example.com/status', 'POST');
$a->getMessagesConfig()->setWebhook('inbound_url', 'https://example.com/inbound', 'POST');
$a->getRtcConfig()->setWebhook('event_url', 'https://example.com/event', 'POST');
$a->disableVbc();

$client->applications()->create($a);

获取应用程序

您可以遍历所有应用程序。

foreach($client->applications()->getAll() as $application){
    echo $application->getName() . PHP_EOL;
}

或者您可以使用字符串 UUID 或应用程序对象获取应用程序。

$application = $client->applications()->get('1a20a124-1775-412b-b623-e6985f4aace0');

更新应用程序

一旦您有了应用程序对象,您就可以修改并保存它。

$application = $client->applications()->get('1a20a124-1775-412b-b623-e6985f4aace0');

$application->setName('Updated Application');
$client->applications()->update($application);

列出您的号码

您可以列出您账户拥有的号码,并可选择包括过滤。

search_pattern:

  • 0 - 号码以 pattern 开头
  • 1 - 号码包含 pattern
  • 2 - 号码以 pattern 结尾
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter
    ->setPattern(234)
    ->setSearchPattern(\Vonage\Numbers\Filter\OwnedNumbers::SEARCH_PATTERN_CONTAINS)
;
$response = $client->numbers()->searchOwned($filter);

has_application:

  • true - 该号码连接到应用程序
  • false - 该号码未连接到应用程序
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter->setHasApplication(true);
$response = $client->numbers()->searchOwned($filter);

application_id:

  • 提供一个应用程序 ID 以获取与请求应用程序关联的所有号码。
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter->setApplicationId("66c04cea-68b2-45e4-9061-3fd847d627b8");
$response = $client->numbers()->searchOwned($filter);

搜索可用的号码

您可以在特定国家搜索可供购买的号码。

$numbers = $client->numbers()->searchAvailable('US');

默认情况下,这将仅返回前 10 个结果。您可以通过添加额外的 \Vonage\Numbers\Filter\AvailableNumbers 过滤器来缩小搜索范围。

购买号码

要购买号码,您可以将从号码搜索返回的值传递进来。

$numbers = $client->numbers()->searchAvailable('US');
$number = $numbers->current();
$client->numbers()->purchase($number->getMsisdn(), $number->getCountry());

或者您可以手动指定号码和国家。

$client->numbers()->purchase('14155550100', 'US');

更新号码

要更新号码,使用 numbers()->update 并传递您想要更改的配置选项。要清除设置,请传递空值。

$number = $client->numbers()->get(VONAGE_NUMBER);
$number
    ->setAppId('1a20a124-1775-412b-b623-e6985f4aace0')
    ->setVoiceDestination('447700900002', 'tel')
    ->setWebhook(
        \Vonage\Number\Number::WEBHOOK_VOICE_STATUS,
        'https://example.com/webhooks/status'
    )
    ->setWebhook(
        \Vonage\Number\Number::WEBHOOK_MESSAGE,
        'https://example.com/webhooks/inbound-sms'
    )
;
$client->numbers()->update($number);
echo "Number updated" . PHP_EOL;

取消号码

要取消号码,提供 msisdn

$client->numbers()->cancel('447700900002');

管理密钥

提供了一个 API,允许您轮换您的 API 密钥。您可以为所有应用程序更新后创建一个新密钥(最多两个密钥)并删除现有的一个。

获取密钥列表

$secretsCollection = $client->account()->listSecrets(API_KEY);
/** @var \Vonage\Account\Secret $secret */
foreach($secretsCollection->getSecrets() as $secret) {
    echo "ID: " . $secret->getId() . " (created " . $secret->getCreatedAt() .")\n";
}

您可以创建一个新的密钥(创建日期将帮助您知道哪个是哪个)

$client->account()->createSecret(API_KEY, 'awes0meNewSekret!!;');

并删除旧密钥(任何仍在使用这些凭据的应用程序将停止工作)

try {
    $response = $client->account()->deleteSecret(API_KEY, 'd0f40c7e-91f2-4fe0-8bc6-8942587b622c');
} catch(\Vonage\Client\Exception\Request $e) {
    echo $e->getMessage();
}

定价

前缀定价

如果您知道您想要呼叫的国家的前缀,您可以使用 prefix-pricing 端点来了解拨打该号码的成本。每个前缀可以返回多个国家(例如,1 返回 USCAUM

$results = $client->account()->getPrefixPricing('1');
foreach ($results as $price) {
    echo $price->getCountryCode().PHP_EOL;
    echo $price->getCountryName().PHP_EOL;
    foreach ($price->getNetworks() as $network) {
        echo $network->getName() .' :: '.$network->getCode().' :: '.$network->getPrefixPrice().PHP_EOL;
    }
    echo "----------------".PHP_EOL;
}

检查余额

检查您账户中剩余的信用额。

$response = $client->account()->getBalance();
echo round($response->getBalance(), 2) . " EUR\n";

查看和更改账户配置

检查账户上的当前设置。

$response = $client->account()->getConfig();
print_r($response->toArray());

更新传入短信消息和投递收据的默认回调 URL。

$response = $client->account()->updateConfig([
    "sms_callback_url" => "http://example.com/webhooks/incoming-sms",
    "dr_callback_url" => "http://example.com/webhooks/delivery-receipt"
]);
print_r($response->toArray());

获取号码信息

号码洞察 API 允许用户检查号码是否有效,并了解更多有关如何使用它的信息。

基本和标准使用

您可以使用 basic()standard() 方法(还有一个 advanced() 方法可供使用,但建议使用异步选项以获取高级信息),如下所示

try {
  $insights = $client->insights()->basic(PHONE_NUMBER);

  echo $insights->getNationalFormatNumber();
} catch (Exception $e) {
  // for the Vonage-specific exceptions, try the `getEntity()` method for more diagnostic information
}

在上面的示例中,数据返回在 $insights 变量中。

高级使用

要获取高级洞察,请使用异步功能并提供一个要发送 webhook 的 URL。

try {
  $client->insights()->advancedAsync(PHONE_NUMBER, 'http://example.com/webhooks/number-insights');
} catch (Exception $e) {
  // for the Vonage-specific exceptions, try the `getEntity()` method for more diagnostic information
}

请参阅文档,了解包含您请求的数据的传入webhook中可以期待的内容。

支持的API

故障排除

检查已弃用功能

随着时间的推移,Vonage API会不断发展,添加新功能,更改现有功能的工作方式,并弃用和删除较老的方法和功能。为了帮助开发者了解何时进行弃用更改,SDK将触发一个E_USER_DEPRECATION警告。这些警告不会停止代码的执行,但在生产环境中可能会造成不便。

为此,默认情况下会抑制这些通知。在开发中,您可以通过向\Vonage\Client构造函数传递一个额外的配置选项来启用这些警告,该选项名为show_deprecations。启用此选项将显示所有弃用通知。

$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
    [
        'show_deprecations' => true
    ]
);

如果发现在生产环境中出现大量弃用通知,请确保配置选项不存在,或者至少设置为false

无法获取本地颁发者证书

一些用户由于以下错误而无法发出请求

Fatal error: Uncaught exception 'GuzzleHttp\Exception\RequestException' with message 'cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)'

这是由于某些PHP安装没有附带受信任的CA证书列表。这是一个系统配置问题,不仅与cURL或Vonage无关。

重要:在下一段中,我们提供了一个CA证书包的链接。Vonage不保证此包的安全性,您应在将任何CA包安装到您的机器之前自行审查。

要解决这个问题,请下载受信任的CA证书列表(例如,curl包),并将其复制到您的机器上。完成此操作后,编辑php.ini并设置curl.cainfo参数

# Linux/MacOS
curl.cainfo = "/etc/pki/tls/cacert.pem"
# Windows
curl.cainfo = "C:\php\extras\ssl\cacert.pem"

传递自定义HTTP客户端

我们允许使用任何HTTPlug适配器或PSR-18兼容的HTTP客户端,因此如果您需要,可以创建具有替代配置的客户端,例如,考虑到本地代理,或处理您设置的具体问题。

以下是一个示例,将默认超时时间缩短为5秒,以避免在没有路由到我们的服务器时出现长时间延迟

$adapter_client = new Http\Adapter\Guzzle6\Client(new GuzzleHttp\Client(['timeout' => 5]));
$vonage_client = new Vonage\Client(new Vonage\Client\Credentials\Basic($api_key, $api_secret), [], $adapter_client);

访问响应数据

当出现问题的时候,您会收到一个Exception。Vonage异常类Vonage\Client\Exception\RequestVonage\Client\Exception\Server支持一个额外的getEntity()方法,您可以使用此方法(除getCode()getMessage()外)来获取更多关于错误原因的信息。返回的实体通常与操作相关的对象或API调用的响应对象。

由于Guzzle适配器而导致Composer安装失败

如果您有一个无法与我们的推荐包guzzlehttp/guzzle共存的冲突包安装,那么您可以安装包vonage/client-core以及任何满足php-http/client-implementation要求的包。

请参阅客户端实现Packagist页面以获取选项。

启用请求/响应日志记录

我们的客户端库支持通过PSR-3兼容的日志记录机制记录请求和响应以进行调试。如果将debug选项传递给客户端,并在客户端的服务工厂中设置PSR-3兼容的记录器,我们将使用记录器进行调试目的。

$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic('abcd1234', 's3cr3tk3y'), ['debug' => true]);
$logger = new \Monolog\Logger('test');
$logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__ . '/log.txt', \Monolog\Logger::DEBUG));
$client->getFactory()->set(\PSR\Log\LoggerInterface::class, $logger);

启用调试日志记录可能会记录敏感信息,请不要在生产环境中启用

贡献

这个库正在积极开发中,我们很高兴听到您的反馈!请随时创建一个问题打开一个pull请求,提出您的问题、评论、建议和反馈。