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 */ 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']); $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; } }