diff --git a/app/Console/Commands/ShjFourBCheckCommand.php b/app/Console/Commands/ShjFourBCheckCommand.php
new file mode 100644
index 0000000..b19c7af
--- /dev/null
+++ b/app/Console/Commands/ShjFourBCheckCommand.php
@@ -0,0 +1,317 @@
+ /dev/null 2>&1
+ */
+class ShjFourBCheckCommand extends Command
+{
+ /**
+ * コマンド名と説明
+ *
+ * @var string
+ */
+ protected $signature = 'shj4b:check
+ {--dry-run : 実際の処理を行わず対象のみ表示}
+ {--limit=100 : 処理する最大件数}
+ {--hours=24 : 指定時間以内の決済のみ対象}';
+
+ /**
+ * コマンドの説明
+ *
+ * @var string
+ */
+ protected $description = 'SHJ-4B 兜底チェック - 未処理の決済トランザクションを検索してProcessSettlementJobをディスパッチ';
+
+ /**
+ * SHJ-4B サービス
+ *
+ * @var ShjFourBService
+ */
+ protected $shjFourBService;
+
+ /**
+ * コンストラクタ
+ */
+ public function __construct(ShjFourBService $shjFourBService)
+ {
+ parent::__construct();
+ $this->shjFourBService = $shjFourBService;
+ }
+
+ /**
+ * コマンド実行
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $startTime = now();
+ $isDryRun = $this->option('dry-run');
+ $limit = (int) $this->option('limit');
+ $hours = (int) $this->option('hours');
+
+ $this->info("SHJ-4B チェックコマンド開始");
+ $this->info("実行モード: " . ($isDryRun ? "ドライラン(実際の処理なし)" : "本実行"));
+ $this->info("処理制限: {$limit}件");
+ $this->info("対象期間: {$hours}時間以内");
+
+ // バッチログ作成
+ $batch = BatchLog::createBatchLog(
+ 'shj4b_check',
+ BatchLog::STATUS_START,
+ [
+ 'command' => 'shj4b:check',
+ 'options' => [
+ 'dry_run' => $isDryRun,
+ 'limit' => $limit,
+ 'hours' => $hours,
+ ],
+ 'start_time' => $startTime,
+ ],
+ 'SHJ-4B チェックコマンド開始'
+ );
+
+ try {
+ // 未処理の決済トランザクション取得
+ $unprocessedSettlements = $this->getUnprocessedSettlements($hours, $limit);
+
+ $this->info("未処理決済トランザクション: " . $unprocessedSettlements->count() . "件");
+
+ if ($unprocessedSettlements->isEmpty()) {
+ $this->info("処理対象なし");
+
+ $batch->update([
+ 'status' => BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4B チェック完了 - 処理対象なし',
+ 'success_count' => 0,
+ ]);
+
+ return 0;
+ }
+
+ // 対象一覧表示
+ $this->displayTargets($unprocessedSettlements);
+
+ if ($isDryRun) {
+ $this->info("ドライランモードのため、実際の処理はスキップします");
+
+ $batch->update([
+ 'status' => BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4B チェック完了 - ドライラン',
+ 'success_count' => 0,
+ 'parameters' => json_encode(['targets' => $unprocessedSettlements->pluck('settlement_transaction_id')->toArray()]),
+ ]);
+
+ return 0;
+ }
+
+ // 実際の処理実行
+ $processed = $this->processSettlements($unprocessedSettlements);
+
+ $this->info("処理完了: {$processed['success']}件成功, {$processed['failed']}件失敗");
+
+ $batch->update([
+ 'status' => $processed['failed'] > 0 ? BatchLog::STATUS_ERROR : BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => "SHJ-4B チェック完了 - 成功:{$processed['success']}件, 失敗:{$processed['failed']}件",
+ 'success_count' => $processed['success'],
+ 'error_count' => $processed['failed'],
+ 'parameters' => json_encode($processed),
+ ]);
+
+ return $processed['failed'] > 0 ? 1 : 0;
+
+ } catch (\Throwable $e) {
+ $this->error("SHJ-4B チェック処理でエラーが発生しました: " . $e->getMessage());
+ Log::error('SHJ-4B チェックコマンドエラー', [
+ 'error' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ ]);
+
+ $batch->update([
+ 'status' => BatchLog::STATUS_ERROR,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4B チェック失敗: ' . $e->getMessage(),
+ 'error_details' => $e->getTraceAsString(),
+ 'error_count' => 1,
+ ]);
+
+ return 1;
+ }
+ }
+
+ /**
+ * 未処理の決済トランザクション取得
+ *
+ * @param int $hours
+ * @param int $limit
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ private function getUnprocessedSettlements(int $hours, int $limit)
+ {
+ $cutoffTime = Carbon::now()->subHours($hours);
+
+ // 条件:
+ // 1. 指定時間以内に作成された
+ // 2. contract_payment_numberがnullでない
+ // 3. まだregular_contractのsettlement_transaction_idに関連付けられていない
+ // 4. ProcessSettlementJobが実行されていない(batch_logで確認)
+ $query = SettlementTransaction::where('created_at', '>=', $cutoffTime)
+ ->whereNotNull('contract_payment_number')
+ ->whereNotNull('pay_date')
+ ->whereNotNull('settlement_amount')
+ ->orderBy('created_at', 'asc');
+
+ $settlements = $query->limit($limit)->get();
+
+ // 既に処理済みのものを除外
+ $unprocessed = $settlements->filter(function ($settlement) {
+ return !$this->isAlreadyProcessed($settlement);
+ });
+
+ return $unprocessed;
+ }
+
+ /**
+ * 既に処理済みかチェック
+ *
+ * @param SettlementTransaction $settlement
+ * @return bool
+ */
+ private function isAlreadyProcessed(SettlementTransaction $settlement): bool
+ {
+ // 1. regular_contractの同一contract_payment_numberが既に処理済みかチェック
+ $linkedContract = DB::table('regular_contract')
+ ->where('contract_payment_number', $settlement->contract_payment_number)
+ ->whereNotNull('contract_payment_day')
+ ->exists();
+
+ if ($linkedContract) {
+ return true;
+ }
+
+ // 2. batch_logで処理完了記録があるかチェック
+ $processedInBatch = BatchLog::where('process_name', 'shj4b')
+ ->where('status', BatchLog::STATUS_SUCCESS)
+ ->where('parameters', 'like', '%"settlement_transaction_id":' . $settlement->settlement_transaction_id . '%')
+ ->exists();
+
+ if ($processedInBatch) {
+ return true;
+ }
+
+ // 3. 現在キューに入っているかチェック(簡易版)
+ // 注: より正確にはRedis/DBキューの内容を確認する必要がある
+ $recentJobDispatched = BatchLog::where('process_name', 'shj4b')
+ ->where('parameters', 'like', '%"settlement_transaction_id":' . $settlement->settlement_transaction_id . '%')
+ ->where('created_at', '>=', Carbon::now()->subHours(1))
+ ->exists();
+
+ return $recentJobDispatched;
+ }
+
+ /**
+ * 対象一覧表示
+ *
+ * @param \Illuminate\Database\Eloquent\Collection $settlements
+ */
+ private function displayTargets($settlements)
+ {
+ $this->info("対象の決済トランザクション:");
+ $this->table(
+ ['ID', '契約支払番号', '決済金額', '支払日', '作成日時'],
+ $settlements->map(function ($settlement) {
+ return [
+ $settlement->settlement_transaction_id,
+ $settlement->contract_payment_number,
+ number_format($settlement->settlement_amount) . '円',
+ Carbon::parse($settlement->pay_date)->format('Y-m-d H:i:s'),
+ $settlement->created_at->format('Y-m-d H:i:s'),
+ ];
+ })->toArray()
+ );
+ }
+
+ /**
+ * 決済処理実行
+ *
+ * @param \Illuminate\Database\Eloquent\Collection $settlements
+ * @return array
+ */
+ private function processSettlements($settlements): array
+ {
+ $success = 0;
+ $failed = 0;
+ $results = [];
+
+ foreach ($settlements as $settlement) {
+ try {
+ $this->info("処理中: 決済トランザクションID {$settlement->settlement_transaction_id}");
+
+ // ProcessSettlementJobをディスパッチ
+ ProcessSettlementJob::dispatch(
+ $settlement->settlement_transaction_id,
+ [
+ 'source' => 'shj4b_check_command',
+ 'triggered_at' => now()->toISOString(),
+ ]
+ );
+
+ $success++;
+ $results[] = [
+ 'settlement_transaction_id' => $settlement->settlement_transaction_id,
+ 'status' => 'dispatched',
+ 'message' => 'ProcessSettlementJobディスパッチ成功',
+ ];
+
+ $this->info("✓ 成功: {$settlement->settlement_transaction_id}");
+
+ } catch (\Throwable $e) {
+ $failed++;
+ $results[] = [
+ 'settlement_transaction_id' => $settlement->settlement_transaction_id,
+ 'status' => 'failed',
+ 'error' => $e->getMessage(),
+ ];
+
+ $this->error("✗ 失敗: {$settlement->settlement_transaction_id} - {$e->getMessage()}");
+
+ Log::error('SHJ-4B チェック 個別処理失敗', [
+ 'settlement_transaction_id' => $settlement->settlement_transaction_id,
+ 'error' => $e->getMessage(),
+ ]);
+ }
+ }
+
+ return [
+ 'success' => $success,
+ 'failed' => $failed,
+ 'results' => $results,
+ 'total' => $settlements->count(),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/app/Console/Commands/ShjThreeCommand.php b/app/Console/Commands/ShjThreeCommand.php
index 1af4430..dfb03b9 100644
--- a/app/Console/Commands/ShjThreeCommand.php
+++ b/app/Console/Commands/ShjThreeCommand.php
@@ -106,3 +106,4 @@ class ShjThreeCommand extends Command
}
}
}
+
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
index 4a3c358..0727ba7 100644
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -77,9 +77,13 @@ class LoginController extends Controller
*/
protected function validateLogin(Request $request)
{
+ // 個別未入力メッセージ(仕様1,2)
$request->validate([
- 'ope_id' => 'required|string', // オペレータID(旧システムと同じ)
- 'ope_pass' => 'required|string', // オペレータパスワード(旧システムと同じ)
+ 'ope_id' => 'required|string',
+ 'ope_pass' => 'required|string',
+ ], [
+ 'ope_id.required' => 'ログインIDが未入力です。',
+ 'ope_pass.required' => 'パスワードが未入力です。',
]);
}
@@ -91,6 +95,13 @@ class LoginController extends Controller
*/
protected function attemptLogin(Request $request)
{
+ // 先にIDのみでオペレータ取得して退職フラグを確認(仕様5-1)
+ $opeId = $request->input('ope_id');
+ $operator = \App\Models\Ope::where('ope_id', $opeId)->first();
+ if ($operator && (int)($operator->ope_quit_flag) === 1) {
+ // 退職扱いは認証失敗と同じメッセージ(仕様5-1 と 3/4 統一表示)
+ return false;
+ }
return Auth::attempt($this->credentials($request), false);
}
@@ -118,9 +129,9 @@ class LoginController extends Controller
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
-
$this->clearLoginAttempts($request);
-
+ // 仕様5: ログインIDをセッション保持
+ $request->session()->put('login_ope_id', $request->input('ope_id'));
return redirect()->intended($this->redirectTo);
}
diff --git a/app/Http/Controllers/Webhook/WellnetController.php b/app/Http/Controllers/Webhook/WellnetController.php
new file mode 100644
index 0000000..628e10c
--- /dev/null
+++ b/app/Http/Controllers/Webhook/WellnetController.php
@@ -0,0 +1,427 @@
+getContent();
+ $md5Hash = md5($raw);
+
+ // IP白名单检查(如果配置了)
+ if (!$this->validateClientIp($request->ip())) {
+ Log::warning('SHJ-4A IP白名单验证失败', [
+ 'ip' => $request->ip(),
+ 'content_length' => strlen($raw),
+ ]);
+ return $this->errorResponse('Unauthorized IP', 403);
+ }
+
+ // 事前にログ記録(サイズ上限に注意)
+ Log::info('SHJ-4A Wellnet PUSH received', [
+ 'length' => strlen($raw),
+ 'content_type' => $request->header('Content-Type'),
+ 'ip' => $request->ip(),
+ 'md5_hash' => $md5Hash,
+ ]);
+
+ // 共通バッチログ: start
+ $batch = BatchLog::createBatchLog(
+ 'shj4a',
+ BatchLog::STATUS_START,
+ [
+ 'ip' => $request->ip(),
+ 'content_type' => $request->header('Content-Type'),
+ 'content_length' => strlen($raw),
+ 'md5_hash' => $md5Hash,
+ ],
+ 'SHJ-4A Wellnet PUSH start'
+ );
+
+ try {
+ // 【処理1】幂等性检查 - MD5重复检查
+ $existingByMd5 = SettlementTransaction::where('md5_string', $md5Hash)->first();
+ if ($existingByMd5) {
+ Log::info('SHJ-4A 幂等性: MD5重复检测', [
+ 'md5_hash' => $md5Hash,
+ 'existing_id' => $existingByMd5->settlement_transaction_id,
+ ]);
+
+ $batch->update([
+ 'status' => BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4A 幂等性: MD5重复,直接返回成功',
+ 'success_count' => 0, // 幂等返回不计入成功数
+ ]);
+
+ return $this->successResponse('処理済み(幂等性)');
+ }
+
+ // 【処理2】SOAP/XML解析
+ $xml = @simplexml_load_string($raw);
+ if (!$xml) {
+ throw new \RuntimeException('Invalid XML/SOAP payload');
+ }
+
+ // Body 以下の最初の要素を取得
+ $nsBody = $xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body ?? null;
+ $payloadNode = $nsBody ? current($nsBody->children()) : $xml; // SOAPでなければ素のXML想定
+
+ // XML -> 配列化
+ $payloadArray = json_decode(json_encode($payloadNode), true) ?? [];
+
+ // 【処理3】データ抽出と正規化
+ $data = $this->extractSettlementData($payloadArray, $md5Hash);
+
+ // 【処理4】必須フィールド検証
+ $this->validateRequiredFields($data);
+
+ // 【処理5】複合キー重复检查(contract_payment_number + pay_date + settlement_amount)
+ $existingByComposite = $this->findExistingByCompositeKey($data);
+ if ($existingByComposite) {
+ Log::info('SHJ-4A 幂等性: 複合キー重复検出', [
+ 'contract_payment_number' => $data['contract_payment_number'],
+ 'pay_date' => $data['pay_date'],
+ 'settlement_amount' => $data['settlement_amount'],
+ 'existing_id' => $existingByComposite->settlement_transaction_id,
+ ]);
+
+ $batch->update([
+ 'status' => BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4A 幂等性: 複合キー重复,直接返回成功',
+ 'success_count' => 0,
+ ]);
+
+ return $this->successResponse('処理済み(幂等性)');
+ }
+
+ // 【処理6】データベース取込と関連処理
+ $settlementId = null;
+ DB::transaction(function() use ($data, $batch, &$settlementId) {
+ // 決済トランザクション登録
+ $settlement = SettlementTransaction::create($data);
+ $settlementId = $settlement->settlement_transaction_id;
+
+ // 契約テーブルの軽微な更新(SHJ-4Bで正式更新)
+ RegularContract::where('contract_payment_number', $data['contract_payment_number'])
+ ->update(['contract_updated_at' => now()]);
+
+ // バッチログ成功更新
+ $batch->update([
+ 'status' => BatchLog::STATUS_SUCCESS,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4A Wellnet PUSH stored successfully',
+ 'success_count' => 1,
+ 'parameters' => json_encode([
+ 'settlement_transaction_id' => $settlementId,
+ 'contract_payment_number' => $data['contract_payment_number'],
+ 'settlement_amount' => $data['settlement_amount'],
+ ]),
+ ]);
+
+ Log::info('SHJ-4A 決済トランザクション登録成功', [
+ 'settlement_transaction_id' => $settlementId,
+ 'contract_payment_number' => $data['contract_payment_number'],
+ 'settlement_amount' => $data['settlement_amount'],
+ ]);
+ });
+
+ // 【処理7】SHJ-4B用キュージョブ投入
+ try {
+ $jobContext = [
+ 'contract_payment_number' => $data['contract_payment_number'],
+ 'settlement_amount' => $data['settlement_amount'],
+ 'pay_date' => $data['pay_date'],
+ 'pay_code' => $data['pay_code'],
+ 'triggered_by' => 'shj4a_webhook',
+ 'triggered_at' => $startedAt->toISOString(),
+ ];
+
+ ProcessSettlementJob::dispatch($settlementId, $jobContext);
+
+ Log::info('SHJ-4A ProcessSettlementJob投入成功', [
+ 'settlement_transaction_id' => $settlementId,
+ 'job_context' => $jobContext,
+ ]);
+
+ } catch (\Throwable $jobError) {
+ // キュー投入失敗は警告レベル(メイン処理は成功済み)
+ Log::warning('SHJ-4A ProcessSettlementJob投入失敗', [
+ 'settlement_transaction_id' => $settlementId,
+ 'error' => $jobError->getMessage(),
+ 'note' => '兜底巡検で処理される予定',
+ ]);
+ }
+
+ return $this->successResponse();
+
+ } catch (\Throwable $e) {
+ Log::error('SHJ-4A error', [
+ 'error' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ 'md5_hash' => $md5Hash,
+ ]);
+
+ if (isset($batch)) {
+ $batch->update([
+ 'status' => BatchLog::STATUS_ERROR,
+ 'end_time' => now(),
+ 'message' => 'SHJ-4A failed: ' . $e->getMessage(),
+ 'error_details' => $e->getTraceAsString(),
+ 'error_count' => 1,
+ ]);
+ }
+
+ return $this->errorResponse($e->getMessage());
+ }
+ }
+
+ /**
+ * IP白名单验证
+ *
+ * @param string $clientIp
+ * @return bool
+ */
+ private function validateClientIp(string $clientIp): bool
+ {
+ $whitelist = config('services.wellnet.ip_whitelist', '');
+
+ if (empty($whitelist)) {
+ return true; // 白名单为空时不验证
+ }
+
+ $allowedIps = array_map('trim', explode(',', $whitelist));
+
+ foreach ($allowedIps as $allowedIp) {
+ if (strpos($allowedIp, '/') !== false) {
+ // CIDR記法対応
+ if ($this->ipInRange($clientIp, $allowedIp)) {
+ return true;
+ }
+ } else {
+ // 直接IP比較
+ if ($clientIp === $allowedIp) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * CIDR範囲でのIP检查
+ *
+ * @param string $ip
+ * @param string $range
+ * @return bool
+ */
+ private function ipInRange(string $ip, string $range): bool
+ {
+ list($subnet, $bits) = explode('/', $range);
+ $ip = ip2long($ip);
+ $subnet = ip2long($subnet);
+ $mask = -1 << (32 - $bits);
+ $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
+ return ($ip & $mask) == $subnet;
+ }
+
+ /**
+ * 決済データの抽出と正規化
+ *
+ * @param array $payloadArray
+ * @param string $md5Hash
+ * @return array
+ */
+ private function extractSettlementData(array $payloadArray, string $md5Hash): array
+ {
+ // inData/Result系の取り出し(キー名差異に寛容)
+ $first = function(array $arr, array $keys, $default = null) {
+ foreach ($keys as $k) {
+ if (isset($arr[$k])) return is_array($arr[$k]) ? $arr[$k] : (string)$arr[$k];
+ }
+ return $default;
+ };
+
+ $flat = $payloadArray;
+ // よくある入れ子: { YoyakuNyukin: { inData: {...} } } / { YoyakuNyukinResponse: { YoyakuNyukinResult: {...} } }
+ foreach (['inData','YoyakuSyunoBarCodeResult','YoyakuNyukinResult','YoyakuSyunoETicketResult'] as $k) {
+ if (isset($flat[$k]) && is_array($flat[$k])) { $flat = $flat[$k]; }
+ }
+
+ $data = [
+ 'pay_code' => $first($flat, ['NyukinPayCode','SyunoPayCode','BcPayCode']),
+ 'contract_payment_number' => $first($flat, ['NyukinRecvNum','SyunoRecvNum','RecvNum','contract_payment_number']),
+ 'corp_code' => $first($flat, ['NyukinCorpCode','SyunoCorpCode','BcCorpCode','CorpCode']),
+ 'mms_date' => $first($flat, ['NyukinReferDate','SyunoMMSNo','MmsDate']),
+ 'cvs_code' => $first($flat, ['NyukinCvsCode','CvsCode']),
+ 'shop_code' => $first($flat, ['NyukinShopCode','ShopCode']),
+ 'pay_date' => $first($flat, ['NyukinPaidDate','PaidDate']),
+ 'settlement_amount' => $first($flat, ['NyukinPaidAmount','SyunoPayAmount','PaidAmount']),
+ 'stamp_flag' => $first($flat, ['NyukinInshiFlag','InshiFlag']),
+ 'status' => 'received',
+ 'md5_string' => $md5Hash,
+ ];
+
+ // データ正規化処理
+ $data = $this->normalizeSettlementData($data);
+
+ return $data;
+ }
+
+ /**
+ * 決済データの正規化
+ *
+ * @param array $data
+ * @return array
+ */
+ private function normalizeSettlementData(array $data): array
+ {
+ // 金額を数値化(非負数)
+ if (!empty($data['settlement_amount'])) {
+ $amount = preg_replace('/[^\d.]/', '', $data['settlement_amount']);
+ $data['settlement_amount'] = max(0, (float)$amount);
+ } else {
+ $data['settlement_amount'] = null;
+ }
+
+ // 支払日時の正規化
+ if (!empty($data['pay_date'])) {
+ try {
+ $data['pay_date'] = Carbon::parse($data['pay_date'])->format('Y-m-d H:i:s');
+ } catch (\Throwable $e) {
+ Log::warning('SHJ-4A 支払日時解析失敗', [
+ 'original_pay_date' => $data['pay_date'],
+ 'error' => $e->getMessage(),
+ ]);
+ $data['pay_date'] = null;
+ }
+ }
+
+ // 文字列フィールドのトリム
+ $stringFields = ['pay_code', 'contract_payment_number', 'corp_code', 'mms_date', 'cvs_code', 'shop_code', 'stamp_flag'];
+ foreach ($stringFields as $field) {
+ if (isset($data[$field])) {
+ $data[$field] = trim($data[$field]) ?: null;
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * 必須フィールドの検証
+ *
+ * @param array $data
+ * @throws \RuntimeException
+ */
+ private function validateRequiredFields(array $data): void
+ {
+ // 必須フィールドのチェック
+ if (empty($data['contract_payment_number'])) {
+ throw new \RuntimeException('必須フィールドが不足: contract_payment_number (RecvNum)');
+ }
+
+ if (!isset($data['settlement_amount']) || $data['settlement_amount'] === null) {
+ throw new \RuntimeException('必須フィールドが不足: settlement_amount');
+ }
+
+ if (empty($data['pay_date'])) {
+ throw new \RuntimeException('必須フィールドが不足: pay_date');
+ }
+ }
+
+ /**
+ * 複合キーによる既存レコード検索
+ *
+ * @param array $data
+ * @return SettlementTransaction|null
+ */
+ private function findExistingByCompositeKey(array $data): ?SettlementTransaction
+ {
+ return SettlementTransaction::where('contract_payment_number', $data['contract_payment_number'])
+ ->where('pay_date', $data['pay_date'])
+ ->where('settlement_amount', $data['settlement_amount'])
+ ->first();
+ }
+
+ /**
+ * 成功レスポンスの生成
+ *
+ * @param string $message
+ * @return \Illuminate\Http\Response
+ */
+ private function successResponse(string $message = '正常処理'): \Illuminate\Http\Response
+ {
+ $responseFormat = config('services.wellnet.response_format', 'json');
+
+ if ($responseFormat === 'soap') {
+ return $this->soapResponse(0, $message);
+ } else {
+ return response()->json(['result' => 0, 'message' => $message]);
+ }
+ }
+
+ /**
+ * エラーレスポンスの生成
+ *
+ * @param string $message
+ * @param int $httpCode
+ * @return \Illuminate\Http\Response
+ */
+ private function errorResponse(string $message, int $httpCode = 500): \Illuminate\Http\Response
+ {
+ $responseFormat = config('services.wellnet.response_format', 'json');
+
+ if ($responseFormat === 'soap') {
+ return $this->soapResponse(1, $message, $httpCode);
+ } else {
+ $resultCode = ($httpCode >= 500) ? 1 : 2; // サーバーエラー:1, クライアントエラー:2
+ return response()->json(['result' => $resultCode, 'error' => $message], $httpCode);
+ }
+ }
+
+ /**
+ * SOAP形式のレスポンス生成
+ *
+ * @param int $resultCode
+ * @param string $message
+ * @param int $httpCode
+ * @return \Illuminate\Http\Response
+ */
+ private function soapResponse(int $resultCode, string $message, int $httpCode = 200): \Illuminate\Http\Response
+ {
+ $soapEnvelope = ''
+ . '
{{ __('ログインID、パスワードを入力して') }}
{{ __('ログインボタンをクリックしてください') }}