samuelmwangiw/africastalking-laravel

这是我创建的africastalking-laravel包


README

Latest Version on Packagist run-tests PHPStan Code styling Total Downloads

这是一个非官方的Laravel SDK,用于与Africa's Talking API交互,利用了Laravel的原生组件,如

安装

您可以通过Composer安装此包

composer require samuelmwangiw/africastalking-laravel

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="africastalking-config"

这是发布配置文件的内容

return [
    'username' => env('AFRICASTALKING_USERNAME', 'sandbox'),
    'api-key' => env('AFRICASTALKING_API_KEY'),
    'sms' => [
        'from' => env('AFRICASTALKING_FROM'),
    ],
    'payment' => [
        'product-name' => env('AFRICASTALKING_PAYMENT_PRODUCT'),
    ],
    'voice' => [
        'from' => env('AFRICASTALKING_VOICE_PHONE_NUMBER'),
    ]
];

您应该通过设置env变量在您的.env文件中配置此包。

使用方法

应用余额

use SamuelMwangiW\Africastalking\Facades\Africastalking;

/** @var \SamuelMwangiW\Africastalking\ValueObjects\Balance $account */
$account = Africastalking::application()->balance();

// Or using the global helper function
$account = africastalking()->application()->balance();

批量消息

发送消息的基本示例

use SamuelMwangiW\Africastalking\Facades\Africastalking;

$response = Africastalking::sms('Hello mom!')
        ->to('+254712345678')
        ->send();

// Or using the global helper function
$response = africastalking()->sms("Hello Mom")
        ->to('+254712345678')
        ->send();

其他有效示例

use SamuelMwangiW\Africastalking\Facades\Africastalking;

$response = Africastalking::sms('It is quality rather than quantity that matters. - Lucius Annaeus Seneca')
        ->message("We made it!") //overwrites any text previously set
        ->text("Look, am on the internet") //alias to message()
        ->as('MyBIZ') // optional: When the senderId is different from `config('africastalking.sms.from')`
        ->to(['+254712345678','+256706123567'])
        ->bulk() // optional: Messages are bulk by default
        ->enqueue() //used for Bulk SMS clients that would like to deliver as many messages to the API before waiting for an acknowledgement from the Telcos
        ->send()

// Or using the global helper function
$response = africastalking()->sms()
        ->message("Hello Mom") //overwrites any text previously set
        ->to('+254712345678')
        ->send();

响应是\SamuelMwangiW\Africastalking\ValueObjects\RecipientsApiResponse对象集合

增值消息

use SamuelMwangiW\Africastalking\Facades\Africastalking;

$response = Africastalking::sms('It is quality rather than quantity that matters. - Lucius Annaeus Seneca')
        ->as('90012') // optional: When the senderId is different from `config('africastalking.sms.from')`
        ->to(['+254712345678','+256706123567'])
        ->premium() // Required to designate messages as bulk
        ->bulkMode(false) // True to send premium messages in bulkMode and false to send as premium
        ->retry(2) //specifies the number of hours your subscription message should be retried in case it’s not delivered to the subscriber.
        ->keyword('keyword') // optional:
        ->linkId('message-link-id') // optional:
        ->send()

响应是\SamuelMwangiW\Africastalking\ValueObjects\RecipientsApiResponse对象集合

话费

分配话费的基本示例

use SamuelMwangiW\Africastalking\Facades\Africastalking;

$response = Africastalking::airtime()
        ->to('+254712345678','KES',100)
        ->send();

// Or using the global helper function
$response = africastalking()->airtime()
        ->to('+256706345678','UGX',100)
        ->send();

您也可以传递一个AirtimeTransaction实例

use SamuelMwangiW\Africastalking\Facades\Africastalking;
use SamuelMwangiW\Africastalking\ValueObjects\AirtimeTransaction;
use SamuelMwangiW\Africastalking\ValueObjects\PhoneNumber;
use SamuelMwangiW\Africastalking\Enum\Currency;

$transaction = new AirtimeTransaction(PhoneNumber::make('+256769000000'),Currency::UGANDA,1000)

$response = Africastalking::airtime()
        ->to($transaction)
        ->send();

Airtime类提供了一个add()方法,基本上是to()的别名,由于这两个方法都可以流畅地链式调用,它解锁了添加接收者循环并最后发送的功能

use App\Models\Clients;

$airtime = africastalking()->airtime();

Clients::query()->chunk(1000, function ($clients) use($airtime) {
    foreach ($clients as $client) {
        $airtime->add($client->phone,'TZS',3000);
    }
});
$results = $airtime->send();

USSD响应

此包允许通过公开一个实现Laravel的Responsable合约的\SamuelMwangiW\Africastalking\Response\UssdResponse类来轻松创建USSD响应

要发送USSD响应,只需在控制器中返回africastalking()->ussd()

ussd可选项接受2个参数并返回一个UssdResponse实例

  • response - 要显示给客户端的响应消息
  • expectsInput - 一个布尔值,指示是否提示用户输入。默认值为true

UssdResponse类有以下方法,可以流畅地链式调用

  • response - 接收要显示给客户端的响应消息作为参数
  • expectsInput - 接收要显示给客户端的expectsInput布尔值作为参数。默认值为true
  • end - 是expectsInput()的别名,但总是设置布尔值为false

以下是一个示例控制器,它使用了UssdResponse和Ussd的HttpRequest

<?php

namespace App\Http\Controllers;

use App\Models\Client;
use Illuminate\Support\Str;
use SamuelMwangiW\Africastalking\Http\Requests\UssdEventRequest;
use SamuelMwangiW\Africastalking\Http\Requests\UssdSessionRequest;

class UssdController extends Controller
{
    public function session(UssdSessionRequest $request)
    {
        if (!$request->userInput()) {
            return africastalking()->ussd('Kindly enter your account number');
        }

        $account = Client::query()
            ->whereAccountNo(
                Str::of($request->userInput())->afterLast('*')->toString()
            )->first();

        if ($account?->exists()) {
            return africastalking()
                ->ussd("Your account Balance is KES {$account->balance}")->end();
        }

        return africastalking()
            ->ussd("The account you entered does not exists.\n\nKindly enter a valid account number");
    }

    public function event(UssdEventRequest $request)
    {
       //Handle the USSD event here
       
        return response('OK');
    }
}

支付(wip)

移动结账

africastalking()
    ->payment()
    ->mobileCheckout()
    ->to('+254720123123')
    ->amount(5000)
    ->currency('KES')
    ->send()

钱包余额

/** @var \SamuelMwangiW\Africastalking\ValueObjects\Balance $balance **/
$balance = africastalking()->wallet()->balance();

储值卡充值

africastalking()
    ->stash()
    ->topup('TZS',100000);

//or fluently
africastalking()
    ->stash()
    ->amount(10000)
    ->currency('USD')
    ->product('My Product') //To override the product name in config
    ->topup(); //topup() has an alias named send() if you fancy

语音响应

此包提供了一个简单直观的语音响应构建器,允许以下任何组合

请注意,在文档中标记为可选的所有参数也是可选的

<?php

return africastalking()->voice()
    ->say(message: '', playBeep: "false", voice: "en-US-Standard-C")
    ->play(url: 'https://example.com/audio.wav')
    ->getDigits(
        say: 'Please enter your account number followed by the hash sign',
        finishOnKey: '#',
        timeout: '30',
        callbackUrl: 'http://mycallbackURL.com',
    )->dial(
        phoneNumbers: ['+254711XXXYYY', '+25631XYYZZZZ', 'test@ke.sip.africastalking.com'],
        record: true,
        ringBackTone: 'http://mymediafile.com/playme.mp3',
        maxDuration: 5,
        sequential: false,
        callerId: '+254711XXXYYY',
    )->record(
        say: 'Please enter your account number followed by the hash sign',
        finishOnKey: '#',
        timeout: '30',
        maxLength: 10,
        playBeep: true,
        trimSilence: true
    )->redirect(
        url: 'http://www.myotherhandler.com/process.php',
    )->reject();

以下是一个控制器示例

<?php

namespace App\Http\Controllers\CallCenter;

use SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest;

class HandleCallsController
{
    public function __invoke(VoiceCallRequest $request)
    {
        if ($request->input('isActive')){
            return africastalking()->voice()
                       ->say('Welcome to Unicorn bank.')
                       ->getDigits(
                           say:'Please enter your account Number followed by the # key',
                           finishOnKey: '#'
                       )
        }
        
        return response('OK');
    }
}
<?php

namespace App\Http\Controllers\CallCenter;

use SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest;

class RecordCallsController
{
    public function __invoke(VoiceCallRequest $request)
    {
        if ($request->input('isActive')){
            return africastalking()->voice()
                       ->say('Our working hours are 9AM - 7PM, Monday to to Friday')
                       ->record(
                            say: 'Please leave a message after the tone.',
                            finishOnKey: '#',
                            playBeep: true,
                            maxLength: 10,
                            trimSilence: true,
                       );
        }
        
        return response('OK');
    }
}
<?php

namespace App\Http\Controllers\CallCenter;

use SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest;

class RejectCallsController
{
    public function __invoke(VoiceCallRequest $request)
    {
        if ($request->input('isActive')){
            return africastalking()->voice()
                       ->say('Our working hours are 9AM - 7PM, Monday to to Friday')
                       ->reject();
        }
        
        return response('OK');
    }
}
<?php

namespace App\Http\Controllers\CallCenter;

use App\Models\Doctor;
use SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest;

class ForwardCallsController
{
    public function __invoke(VoiceCallRequest $request)
    {
        if ($request->input('isActive')){
            $doctor = Doctor::query()->onDuty()->first();
            
            return africastalking()->voice()
                       ->dial(
                            phoneNumbers: [$doctor->number],
                            record: true,
                            ringBackTone: "https://example.com/marketing-tone.wave"
                       );
        }
        
        return response('OK');
    }
}

合成语音属性。

<Say />动作支持使用语音合成标记语言(SSML)的使用

要使用合成语音进行响应,请在上方通过一个回调say()作为第一个参数传递,接收一个SynthesisedSpeech对象实例

<?php

namespace App\Http\Controllers\CallCenter;

use SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest;
use SamuelMwangiW\Africastalking\ValueObjects\Voice\SynthesisedSpeech;

class HandleCallsController
{
    public function __invoke(VoiceCallRequest $request)
    {
        if ($request->input('isActive')){
            return africastalking()->voice()
                       ->say(
                         fn(SynthesisedSpeech $speech) => $speech
                                 ->say('Welcome to Wasafi. Your airtime balance is')
                                 ->sayAsCurrency('$1000','en-US')
                                 ->say(' and expires on ')
                                 ->sayAsDate('20420420')
                                 ->say(' at ')
                                 ->sayAsTime('04:42PM')
                                 ->pause('69ms')
                                 ->say('For assistance Call our customer service team on ')
                                 ->sayAsTelephone('0800694269')
                                 ->bleep('Thank you for choosing us 😜')
                       )
        }
        
        return response('OK');
    }
}

注意 在XML响应中,您只能有一个单个的 <Say />

发起通话

// Most basic call
africastalking()->voice()
    ->call('+254720123123')
    ->done();

// Call a list of users
africastalking()->voice()
    ->call(['+254720123123','+254731234567'])
    ->done();

// override the callerId
africastalking()->voice()
    ->call('+254720123123')
    ->as('+254711082999')
    ->done();

// Set the call Request Id
africastalking()->voice()
    ->call('+254720123123')
    ->requestId('id_12345')
    ->done();

// You can also use send if like that better
africastalking()->voice()
    ->call('+254720123123')
    ->send();

WebRTC

<?php

namespace App\Http\Controllers\Voice;

class WebRtcTokenController {
    public function __invoke()
    {
        $clientName = auth()->user()?->name ?? 'Browser';
        
        $token = africastalking()
            ->voice()
            ->webrtc()
            ->for($clientName)
            ->token();
        
        return [
            'token' => $token->token,
            'clientName' => $token->clientName,
            'expire' => $token->lifeTimeSec,
        ];
    }
}

HTTP请求

该软件包附带以下 Laravel 请求,您可以将它们注入到您的应用程序控制器中

\SamuelMwangiW\Africastalking\Http\Requests\AirtimeStatusRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\AirtimeValidationRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\BulkSmsOptOutRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\IncomingMessageRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\MessageDeliveryRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\MobileC2BValidationRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\PaymentNotificationRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\SubscriptionRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\UssdEventRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\UssdSessionRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\VoiceCallRequest::class;
\SamuelMwangiW\Africastalking\Http\Requests\VoiceEventRequest::class;

除了在漂亮的FormRequest对象中公开post参数外,这些类还包含适用的辅助方法,例如:

  • id() 用于检索每个请求关联的唯一ATPid
  • phone() 用于检索客户的电话号码
  • userInput() 用于检索ussd用户输入
  • status() 用于获取交易/请求最终状态
  • deliveryFailed() 返回一个布尔值 true,如果短信或空中充值交付失败,否则返回 false
  • 等等

消息交付回调动作控制器示例

<?php

namespace App\Http\Controllers\Messaging;

use App\Models\Message;
use SamuelMwangiW\Africastalking\Http\Requests\MessageDeliveryRequest;

class MessageDeliveredController{
    public function __invoke(MessageDeliveryRequest $request)
    {
        $message = Message::query()
                            ->where(['transaction_id'=>$request->id()])
                            ->firstOrFail();
                            
        $message->update([
            'delivered_at'=>now(),
            'status'=>$request->status(),
        ]);
        
        return response('OK');
    }
}

通知

该软件包附带一个通道,允许通过Africastalking SMS轻松路由通知。

要使用Africastalking路由通知,在您的通知 via 方法中返回 SamuelMwangiW\Africastalking\Notifications\AfricastalkingChannel,并在 toAfricastalking 方法中发送要发送的文本消息

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use SamuelMwangiW\Africastalking\Facades\Africastalking;
use SamuelMwangiW\Africastalking\Notifications\AfricastalkingChannel;

class WelcomeNotification extends Notification
{
    public function via($notifiable)
    {
        return [AfricastalkingChannel::class];
    }

    public function toAfricastalking($notifiable)
    {
        return "Hi {$notifiable->name}. Your account at Unicorn Bank has been created. Hope you enjoy the service";
    }
}

还请确保通知模型实现了 SamuelMwangiW\Africastalking\Contracts\ReceivesSmsMessages,并且模型的 routeNotificationForAfricastalking() 返回接收消息的电话号码

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
use SamuelMwangiW\Africastalking\Contracts\ReceivesSmsMessages;

class User extends Model implements ReceivesSmsMessages
{
    protected $fillable = ['email','name','phone'];

    public function routeNotificationForAfricastalking(Notification $notification): string
    {
        return $this->phone;
    }
}

测试

composer test

变更日志

请参阅 变更日志 以获取有关最近更改的更多信息。

贡献

请参阅 贡献指南 以获取详细信息。

安全漏洞

请查阅 我们的安全策略 了解如何报告安全漏洞。

鸣谢

许可协议

MIT许可协议(MIT)。请参阅 许可文件 以获取更多信息。