| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- <?php
- namespace App\Http\Traits;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Http;
- use Illuminate\Support\Facades\Cookie;
- use App\Models\DTO\Toss\AuthData;
- use App\Models\DTO\Toss\CancelData;
- trait TossTrait
- {
- use CommonTrait;
- /**
- * 토스 API Client Key
- */
- protected function getClientKey(): string
- {
- return (config('use_pg_test', 0) ? config('test_client_key') : config('live_client_key'));
- }
- /**
- * 토스 API Secret Key
- */
- protected function getSecretKey(): string
- {
- return (config('use_pg_test', 0) ? config('test_secret_key') : config('live_secret_key'));
- }
- /**
- * 토스 인증 일련번호
- */
- protected function getAuthorization(): string
- {
- return ('Basic ' . base64_encode($this->getSecretKey() . ':'));
- }
- /**
- * 토스 실 본인인증 사용 여부
- */
- protected function getTossCertIsTest(): bool
- {
- return config('toss_cert_is_test', 0);
- }
- /**
- * 토스 카드사 정보
- */
- protected function getCards(): array
- {
- return [
- '3K' => '기업비씨', '46' => '광주', '71' => '롯데', '30' => '산업',
- '31' => 'BC카드', '51' => '삼성카드', '38' => '새마을', '41' => '신한',
- '62' => '신협', '36' => '씨티', '33' => '우리', 'W1' => '우리',
- '37' => '우체국', '39' => '저축', '35' => '전북', '42' => '제주',
- '15' => '카카오뱅크', '3A' => '케이뱅크', '24' => '토스뱅크', '21' => '하나',
- '61' => '현대', '11' => '국민', '91' => '농협', '34' => '수협'
- ];
- }
- /**
- * 토스 은행/증권사 정보
- */
- protected function getBanks(): array
- {
- return [
- '39' => '경남은행', '34' => '광주은행', 'S8' => '교보증권', '12' => '단위농협(지역농축협)',
- 'SE' => '대신증권', 'SK' => '메리츠증권', 'S5' => '미래에셋증권', 'SM' => '부국증권',
- '32' => '부산은행', 'S3' => '삼성증권', '45' => '새마을금고', '64' => '산림조합',
- 'SN' => '신영증권', 'S2' => '신한금융투자', '88' => '신한은행', '48' => '신협',
- '27' => '씨티은행', '20' => '우리은행', '71' => '우체국예금보험', 'S0' => '유안타증권',
- 'SJ' => '유진투자증권', '50' => '저축은행중앙회', '37' => '전북은행', '35' => '제주은행',
- '90' => '카카오뱅크', '288' => '카카오페이증권', '89' => '케이뱅크', '92' => '토스뱅크',
- 'ST' => '토스증권', 'SR' => '펀드온라인코리아(한국포스증권)', 'SH' => '하나금융투자', '81' => '하나은행',
- 'S9' => '하이투자증권', 'S6' => '한국투자증권', 'SG' => '한화투자증권', 'SA' => '현대차증권',
- '54' => '홍콩상하이은행', 'SI' => 'DB금융투자', '31' => 'DGB대구은행', '03' => 'IBK기업은행',
- '06' => 'KB국민은행', 'S4' => 'KB증권', '02' => 'KDB산업은행', 'SP' => 'KTB투자증권(다올투자증권)',
- 'SO' => 'LIG투자증권', '11' => 'NH농협은행', 'SL' => 'NH투자증권', '23' => 'SC제일은행',
- '07' => 'Sh수협은행', 'SD' => 'SK증권'
- ];
- }
- /**
- * 카드 혜택 조회
- */
- protected function requestCardPromotions(): mixed
- {
- $response = Http::withHeaders([
- 'Authorization' => $this->getAuthorization(),
- ])->get('https://api.tosspayments.com/v1/promotions/card');
- $res = $response->json();
- if (isset($res['interestFreeCards']) > 0) {
- $interestFreeCards = $res['interestFreeCards'];
- foreach ($interestFreeCards as $i => $row) {
- $res['interestFreeCards'][$i]['min'] = min($row['installmentFreeMonths']);
- $res['interestFreeCards'][$i]['max'] = max($row['installmentFreeMonths']);
- $res['interestFreeCards'][$i]['minimumPaymentAmountKor'] = $this->numberToHangul($row['minimumPaymentAmount']);
- }
- }
- return $res;
- }
- /**
- * 결제 승인 API 호출
- */
- protected function requestPayment(string $paymentKey, string $orderId, int $amount): mixed
- {
- // 기본 결제 요청
- $response = Http::withHeaders([
- 'Authorization' => $this->getAuthorization(),
- 'Content-Type' => 'application/json'
- ])->post('https://api.tosspayments.com/v1/payments/confirm', [
- 'paymentKey' => $paymentKey,
- 'orderId' => $orderId,
- 'amount' => $amount
- ]);
- return $response->json();
- }
- /**
- * 결제 취소 API 호출
- */
- protected function requestCancel(string $paymentKey, string $idempotencyKey, CancelData $cancelData): mixed
- {
- // 기본 결제 요청
- $response = Http::withHeaders([
- 'Authorization' => $this->getAuthorization(),
- 'Content-Type' => 'application/json',
- 'Idempotency-Key' => $idempotencyKey,
- ])->post(sprintf('https://api.tosspayments.com/v1/payments/%s/cancel', $paymentKey),
- $cancelData->toArray()
- );
- return $response->json();
- }
- /**
- * 본인확인 Access Token 요청
- */
- protected function requestAccessToken(Request $request): ?array
- {
- $tossCertIsTest = $this->getTossCertIsTest();
- if (!$request->hasCookie('tossAccessToken')) {
- $token = Http::asForm()->post('https://oauth2.cert.toss.im/token', [
- 'grant_type' => 'client_credentials',
- 'client_id' => ($tossCertIsTest ? config('test_toss_cert_client_id') : config('live_toss_cert_client_id')),
- 'client_secret' => ($tossCertIsTest ? config('test_toss_cert_client_secret') : config('live_toss_cert_client_secret')),
- 'scope' => 'ca'
- ])->json();
- } else {
- $token = unserialize($request->cookie('tossAccessToken'));
- if ($token['tossCertIsTest'] != $tossCertIsTest) {
- Cookie::expire('tossAccessToken');
- $token = $this->requestAccessToken($request);
- }
- }
- return ($token + ['tossCertIsTest' => $tossCertIsTest]);
- }
- /**
- * 본인확인 요청
- */
- protected function requestUserAuth(array $token, AuthData $authData): object|array|null
- {
- return Http::asJson()->withHeaders([
- 'Authorization' => sprintf("%s %s", $token['token_type'], $token['access_token'])
- ])->post('https://cert.toss.im/api/v2/sign/user/auth/id/request', $authData->toArray())->object();
- }
- /**
- * 본인확인 상태 조회
- */
- protected function requestUserAuthStatus(array $token, string $txId): object|array|null
- {
- return Http::asJson()->withHeaders([
- 'Authorization' => sprintf("%s %s", $token['token_type'], $token['access_token'])
- ])->post('https://cert.toss.im/api/v2/sign/user/auth/id/status', [
- 'txId' => $txId,
- ])->object();
- }
- /**
- * 본인확인 결과 확인
- */
- protected function requestCertResult(array $token, string $txId, string $sessionKey): object|array|null
- {
- return Http::asJson()->withHeaders([
- 'Authorization' => sprintf("%s %s", $token['token_type'], $token['access_token'])
- ])->post('https://cert.toss.im/api/v2/sign/user/auth/id/result', [
- 'txId' => $txId,
- 'sessionKey' => $sessionKey
- ])->object();
- }
- /**
- * 본인확인 결과 조회
- */
- protected function getTossCertResult(array $token, string $txId): ?object
- {
- $sessionId = $this->generateSessionId();
- $secretKey = $this->generateRandomBytes(32);
- $iv = $this->generateRandomBytes(12);
- $sessionKey = $this->generateSessionKey($sessionId, $secretKey, $iv);
- $result = $this->requestCertResult($token, $txId, $sessionKey);
- if ($result->resultType == 'FAIL') {
- return $result;
- }
- $personalData = $result->success->personalData;
- $result->success->personalData = (object)[
- 'ci' => $this->decryptData($secretKey, $iv, $personalData->ci),
- 'name' => $this->decryptData($secretKey, $iv, $personalData->name),
- 'birthday' => $this->decryptData($secretKey, $iv, $personalData->birthday),
- 'gender' => $this->decryptData($secretKey, $iv, $personalData->gender),
- 'nationality' => $this->decryptData($secretKey, $iv, $personalData->nationality),
- 'di' => $this->decryptData($secretKey, $iv, $personalData->di)
- ];
- return $result;
- }
- }
|