|
- <?php
-
- namespace App\Logic\SMS;
-
- use App\Codes\SMSProviderName;
- use App\Codes\SMSSendPurpose;
- use App\Models\ReceiptIssuingOrder;
- use App\Models\SMSProvider;
- use App\Models\SMSProviderFourSMessageCommunication;
- use App\Models\SMSSendOrder;
- use App\Util\DateUtil;
- use Exception;
- use Illuminate\Http\Client\Response;
- use Illuminate\Support\Collection;
- use Illuminate\Support\Facades\Http;
- use LogicException;
-
- class FourSMessageManager implements SMSManager
- {
-
-
- private const SEND_URL = ['POST', "https://4sm.jp/api/sms_send"];
- private const CANCEL_URL = ['POST', "https://4sm.jp/api/sms_cancel"];
- private const RESULT_URL = ['POST', "https://4sm.jp/api/get_send_result"];
-
- private static function getUserId(): string
- {
- $ret = config("logic.sms.FourSMessage.userId");
- if ($ret === null) {
- throw new LogicException("SMS FourSMessage UserID 未定義");
- }
- return $ret;
- }
-
- private static function getPassword(): string
- {
- $ret = config("logic.sms.FourSMessage.password");
- if ($ret === null) {
- throw new LogicException("SMS FourSMessage Password 未定義");
- }
- return $ret;
- }
-
- public static function makeSMSSendOrder(ReceiptIssuingOrder $receiptIssuingOrder, SMSSendPurpose $purpose, string $contents): SMSSendOrder
- {
-
-
- $order = new SMSSendOrder();
-
-
-
- $order->receipt_issuing_order_id = $receiptIssuingOrder->id;
- $order->contract_id = $receiptIssuingOrder->contract_id;
- $order->phone_number = $receiptIssuingOrder->sms_phone_number;
- $order->summary_key1 = $receiptIssuingOrder->summary_key1;
- $order->summary_key2 = $receiptIssuingOrder->summary_key2;
-
- $order->purpose = $purpose;
- $order->content = $contents;
-
- return $order;
- }
-
- public static function getProvider(): SMSProvider
- {
- return SMSProvider::whereProviderName(SMSProviderName::FOUR_S_MESSAGE->value)->firstOrFail();
- }
-
- public function __construct(
- private SMSSendOrder $order,
- ) {
- }
-
- public function loadOrder(string $id): static
- {
- $this->order = SMSSendOrder::findOrFail($id);
- return $this;
- }
-
- public function setOrder(SMSSendOrder $order): static
- {
- $this->order = $order;
- return $this;
- }
-
-
- public function getOrder()
- {
- return $this->order;
- }
-
- public function send(): bool
- {
-
- $sendContents = [
- 'cp_userid' => static::getUserId(),
- 'cp_password' => static::getPassword(),
- 'carrier_id' => '99',
- 'message' => $this->order->content,
- 'address' => $this->order->phone_number,
- 'urlshorterflg' => '1',
- ];
-
- $this->order->setSMSProvider(static::getProvider());
- $res = $this->communication(self::SEND_URL, $sendContents);
-
-
- if ($res->isSuccess()) {
- // 送信依頼を作成
- $this->order->save();
-
- $comm = new SMSProviderFourSMessageCommunication();
- $comm->sms_send_order_id = $this->order->id;
- $comm->contract_id = $this->order->contract_id;
- $comm->request_id = $res->requestId;
- $comm->request_date = $res->requestDate;
- $comm->save();
-
- return true;
- } else {
- return false;
- }
- }
-
- public function poll(): bool
- {
-
- $requestId = SMSProviderFourSMessageCommunication::whereSmsSendOrderId($this->order->id)
- ->firstOrFail()
- ->request_id;
-
- $sendContents = [
- 'request_id' => $requestId,
- 'user_id' => static::getUserId(),
- 'password' => base64_encode(static::getPassword()),
- ];
-
- $res = $this->communication(self::RESULT_URL, $sendContents);
-
- if ($res->isSuccess()) {
- $res->save();
- }
-
- return $res->isSuccess();
- }
-
-
-
- public function cancel(): bool
- {
-
- $requestId = SMSProviderFourSMessageCommunication::whereSmsSendOrderId($this->order->id)
- ->firstOrFail()
- ->request_id;
-
- $sendContents = [
- 'request_id' => $requestId,
- 'cp_userid' => static::getUserId(),
- 'cp_password' => static::getPassword(),
- ];
-
- $res = $this->communication(self::CANCEL_URL, $sendContents);
-
- return $res->isSuccess();
- }
-
- private function communication(array $urlDef, array $sendData): CommunicationData
- {
-
- $method = $urlDef[0];
-
- $form = Http::withHeaders([
- 'Content-Type' => 'application/x-www-form-urlencoded',
- ])
- ->asForm();
- if ($method === 'GET') {
-
- $query = "";
- foreach ($sendData as $key => $value) {
- if ($query !== "") {
- $query .= '&';
- }
-
- $query .= $key . "=" . $value;
- }
- $url = $urlDef[1] . '?' . $query;
- $res = $form->get($url);
- } else {
- $url = $urlDef[1];
- $res = $form->post($url, $sendData);
- }
-
- logger(['SMS-SendContet' => $sendData, 'URL' => $url]);
-
- if (!$res->ok()) {
- $res->throw();
- }
-
- logger(['SMS-ReveiveContet' => $res->json()]);
-
- $ret = new CommunicationData($res, $this->order);
-
- return $ret;
- }
- }
-
- class CommunicationData
- {
-
- public string|null $result;
- public string|null $requestId;
- public string|null $requestDate;
- public string|null $errorCode;
- public string|null $errorMessage;
-
- /**
- * @var Collection<SMSProviderFourSMessageCommunication>
- */
- public Collection $data;
-
- private SMSSendOrder $order;
-
- private const RESULT_SUCCESS = 'SUCCESS';
-
- private const DATE_FORMAT = 'YmdHis';
-
- public function __construct(Response $res, SMSSendOrder $order)
- {
-
- $this->order = $order;
-
- $data = $res->json();
- $response = data_get($data, 'response');
-
- if ($response !== null) {
- $data = $response;
- }
-
- $this->result = data_get($data, 'result');
- $this->requestId = data_get($data, 'request_id');
- $this->requestDate = data_get($data, 'request_date');
- $this->errorCode = data_get($data, 'error_code');
- $this->errorMessage = data_get($data, 'error_message');
-
- $this->data = collect();
-
- $records = data_get($data, 'records');
- if (is_array($records)) {
-
- foreach ($records as $record) {
- $requestId = data_get($record, 'request_id');
-
- // 空文字の場合があるので、数値にキャストする
- $record['success_count'] = intVal($record['success_count']);
- $record['message_count'] = intVal($record['message_count']);
-
- $ele = SMSProviderFourSMessageCommunication::whereRequestId($requestId)
- ->firstOrFail();
-
-
- $ele->fill($record);
- $ele->sms_send_order_id = $order->id;
-
- $this->data->push($ele);
- }
- }
- }
-
- public function isSuccess(): bool
- {
- return $this->result === self::RESULT_SUCCESS;
- }
-
- public function save()
- {
- foreach ($this->data as $data) {
- $data->save();
-
-
- if ($this->isFixRecord($data)) {
-
- $this->order->done = true;
-
- if ($data->deliv_rcpt_date !== null) {
- $this->order->send_datetime = DateUtil::parse($data->deliv_rcpt_date, self::DATE_FORMAT);
- }
-
- if ($data->success_count > 0) {
- $this->order->cost = $this->calcCost($data);
- }
- }
- }
- }
-
- public function isFixRecord(SMSProviderFourSMessageCommunication $comm): bool
- {
- // 以下のコードになれば「状態確定」のタイミングであると判断できます。
- // ・受付状態 : 90受付取消、または99受付失敗
- // ・送信エラー: 31~35送信エラー、または40送達済
-
- if (in_array($comm->request_status, ['90', '99'])) {
- return true;
- }
-
- if (in_array($comm->sending_status, [
- '31',
- '32',
- '33',
- '34',
- '35',
- '40',
- ])) {
- return true;
- }
-
- return false;
- }
-
- private function calcCost(SMSProviderFourSMessageCommunication $comm): int
- {
- $provider = self::getMst();
-
- return $comm->success_count * $provider->cost;
- }
-
- private static function getMst(): SMSProvider
- {
- static $provider = null;
-
- if ($provider === null) {
- $provider = SMSProvider::whereProviderName(SMSProviderName::FOUR_S_MESSAGE->value)
- ->firstOrFail();
- }
-
- return $provider;
- }
- }
|