결제 준비

엑심베이는 요청된 결제의 위변조 방지를 위해 파라미터 유효성을 검증하고 있습니다. 결제 과정에서 fgkey 는 아래처럼 두 번 필요합니다.

  1. 1. SDK 호출 전: 결제 준비 APIfgkey를 생성해 결제창을 띄울 때 사용합니다.
  2. 2. status_url로 응답받은 후: 결제 검증 API에 응답받은 파라미터를 그대로 보내 유효성을 검증을 진행합니다.

SDK 호출 전 준비

SDK를 사용해 결제창을 띄우기 전 결제 준비 API를 호출해 요청된 결제의 위변조 방지를 위한 fgkey를 생성하세요.

요청
                      
curl --request POST 'https://api-test.eximbay.com/v1/payments/ready' \
--header 'Authorization: Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=' \
--header 'Content-Type: application/json' \
--data '{
      "payment" : {
        "transaction_type" : "PAYMENT",
        "order_id" : "20220819105102",
        "currency" : "USD",
        "amount" : "1",
        "lang" : "EN"
      },
      "merchant" : {
        "mid" : "1849705C64"
      },
      "buyer" : {
        "name" : "eximbay",
        "email" : "test@eximbay.com"
      },
      "url" : {
        "return_url" : "eximbay.com",
        "status_url" : "eximbay.com"
      }
    }'
                      
                    
                      
RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("Authorization", "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=");

URI url = URI.create("https://api-test.eximbay.com/v1/payments/ready");

String body = "{\n" +
			        "\"payment\" : {\n" +
			        "\"transaction_type\" : \"PAYMENT\",\n" +
			        "\"order_id\" : \"20220819105102\",\n" +
			        "\"currency\" : \"USD\",\n" +
			        "\"amount\" : \"1\",\n" +
			        "\"lang\" : \"EN\"\n" +
			        "},\n" +
			        "\"merchant\" : {\n" +
			        "\"mid\" : \"1849705C64\"\n" +
			        "},\n" +
			        "\"buyer\" : {\n" +
			        "\"name\" : \"eximbay\",\n" +
			        "\"email\" : \"test@eximbay.com\"\n" +
			        "},\n" +
			        "\"url\" : {\n" +
			        "\"return_url\" : \"eximbay.com\",\n" +
			        "\"status_url\" : \"eximbay.com\"\n" +
			        " }\n" +
			        "}";

HttpEntity<String> entity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

System.out.println(response.getBody());
                      
                    
                      
<?php
$url = 'https://api-test.eximbay.com/v1/payments/ready';
$data = '{
    "payment": {
        "transaction_type": "PAYMENT",
        "order_id": "20220819105102",
        "currency": "USD",
        "amount": "1",
        "lang": "EN"
    },
    "merchant": {
        "mid": "1849705C64"
    },
    "buyer": {
        "name": "eximbay",
        "email": "test@eximbay.com"
    },
    "url": {
        "return_url": "eximbay.com",
        "status_url": "eximbay.com"
    }
}';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo='));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response  = curl_exec($ch);

echo $response;
curl_close($ch);
?>
                      
                    
                      
import requests
import json

url = "https://api-test.eximbay.com/v1/payments/ready"
headers = {
  "Authorization": "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=",
  "Content-Type": "application/json"
}

request = {
  "payment": {
    "transaction_type": "PAYMENT",
    "order_id": "20220819105102",
    "currnecy": "USD",
    "amount": "1",
    "lang": "EN"
  },
  "merchant": {
    "mid": "1849705C64",
  },
  "buyer": {
    "name": "eximbay",
    "email": "test@eximbay.com"
  },
  "url": {
    "return_url": "eximbay.com",
    "status_url": "eximbay.com"
  }
}
response = requests.post(url, headers=headers, data=json.dumps(request))

print(response.text)
                      
                    
                      
var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api-test.eximbay.com/v1/payments/ready',
  'headers': {
    'Authorization': 'Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "payment": {
      "transaction_type": "PAYMENT",
      "order_id": "20220819105102",
      "currency": "USD",
      "amount": "1",
      "lang": "EN"
    },
    "merchant": {
      "mid": "1849705C64"
    },
    "buyer": {
      "name": "eximbay",
      "email": "test@eximbay.com"
    },
    "url": {
      "return_url": "eximbay.com",
      "status_url": "eximbay.com"
    }
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
                      
                    
                        
string uri = "https://api-test.eximbay.com/v1/payments/ready";
string body = "{\n" +
			        "\"payment\" : {\n" +
			        "\"transaction_type\" : \"PAYMENT\",\n" +
			        "\"order_id\" : \"20220819105102\",\n" +
			        "\"currency\" : \"USD\",\n" +
			        "\"amount\" : \"1\",\n" +
			        "\"lang\" : \"EN\"\n" +
			        "},\n" +
			        "\"merchant\" : {\n" +
			        "\"mid\" : \"1849705C64\"\n" +
			        "},\n" +
			        "\"buyer\" : {\n" +
			        "\"name\" : \"eximbay\",\n" +
			        "\"email\" : \"test@eximbay.com\"\n" +
			        "},\n" +
			        "\"url\" : {\n" +
			        "\"return_url\" : \"eximbay.com\",\n" +
			        "\"status_url\" : \"eximbay.com\"\n" +
			        " }\n" +
			        "}";

WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
webClient.Headers[HttpRequestHeader.Authorization] = "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=";
webClient.Encoding = UTF8Encoding.UTF8;
string responseJSON = webClient.UploadString(uri, body);

Console.Write(responseJSON);
                        
                    
                        
val restTemplate =  RestTemplate()
val headers = HttpHeaders()
headers.add("Content-Type", "application/json")
headers.add("Authorization", "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=")

var url = URI.create("https://api-test.eximbay.com/v1/payments/ready")

val body = "{\n" +
		        "\"payment\" : {\n" +
		        "\"transaction_type\" : \"PAYMENT\",\n" +
		        "\"order_id\" : \"20220819105102\",\n" +
		        "\"currency\" : \"USD\",\n" +
		        "\"amount\" : \"1\",\n" +
		        "\"lang\" : \"EN\"\n" +
		        "},\n" +
		        "\"merchant\" : {\n" +
		        "\"mid\" : \"1849705C64\"\n" +
		        "},\n" +
		        "\"buyer\" : {\n" +
		        "\"name\" : \"eximbay\",\n" +
		        "\"email\" : \"test@eximbay.com\"\n" +
		        "},\n" +
		        "\"url\" : {\n" +
		        "\"return_url\" : \"eximbay.com\",\n" +
		        "\"status_url\" : \"eximbay.com\"\n" +
		        " }\n" +
		        "}"

var entity = HttpEntity<String>(body, headers)
var response = restTemplate.exchange(url, HttpMethod.POST, entity, String::class.java)

println(response.body)
                        
                    

응답

아래와 같이 응답에서 생성된 fgkey를 확인할 수 있습니다. 생성된 fgkey를 그대로 결제창을 호출할 때 넣어서 보내야 합니다.

응답
                  
{
  	"rescode": "0000",
  	"resmsg": "Success",
  	"fgkey": "0E9BE04BA239A519E68171F26B68604ADA0A85C8350DBF5C8C0FCCF98461DB09"
  }
                  
                

SDK 응답받은 후 준비

결제 승인 결과 처리하기

결제창에서 고객이 선택한 결제수단으로 결제를 진행했다면 승인 결과를 결제 요청 시 사용한 status_url 서버로 전송합니다. 결제 승인 결과 데이터는 json 형태가 아닌 쿼리스트링 형태로 전송됩니다.

status_url 서버로 결제 승인 결과를 정상적으로 수신한 경우 주문완료 처리 후 반드시 해당 페이지의 마지막에 rescode와 resmsg를 출력해야 합니다.
• 처리성공: rescode=0000&resmsg=Success • 처리실패: recode=실패코드&resmsg=실패메시지

승인 결과 데이터는 엑심베이 노티 서버에서 응답이 나가기 때문에 가맹점의 방화벽 정책이 있다면 사전에 아래 엑심베이 노티 서버 IP 접근을 허용해야 정상적으로 승인 결과를 수신 받을 수 있습니다.

환경 Source IP Destination IP 용도
테스트계 43.203.92.211 가맹점 서버 IP(Inbound) Eximbay에서 결제 결과를 가맹점 status_url로 전송(운영/테스트 환경 동일)
3.34.20.184
3.37.76.229
운영계 15.165.144.33

결제 검증하기

엑심베이에서 가맹점 status_url 서버로 전송된 쿼리스트링 형태의 결제 결과 데이터에 위변조가 없는지 확인할 수 있습니다.

결제 승인 결과 데이터 예시
                  
currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM
                  
                

status_url로 보내진 결제 승인 결과에 포함되어 있는 fgkey는 결제 준비 API를 호출해 생성한 fgkey와 일치하지 않습니다.
결제 승인 결과 데이터를 기준으로 새롭게 생성된 fgkey입니다.

status_url은 중복 호출될 수 있습니다. 주문이 중복 처리되지 않도록 주의가 필요하며, transaction_id로 중복승인과 호출에 대해서 확인할 수 있습니다.

검증은 결제 검증 API로 데이터의 유효성을 검증할 수 있습니다. 가맹점 status_url 서버로 전송된 쿼리스트링 형태의 결제 결과 데이터를 body 내 data 필드의 value 값으로 그대로 사용해 검증할 수 있습니다.

요청
        
  curl --request POST 'https://api-test.eximbay.com/v1/payments/verify \
  --header 'Authorization: Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=' \
  --header 'Content-Type: application/json' \
  --data '{
  "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
  		    }'
        
      
        
          RestTemplate restTemplate = new RestTemplate();
    
          HttpHeaders headers = new HttpHeaders();
          headers.add("Content-Type", "application/json");
          headers.add("Authorization", "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=");
          
          URI url = URI.create("https://api-test.eximbay.com/v1/payments/verify");
          
          String body = "{\n" +
          "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
          			        "}";
          
          HttpEntity<String> entity = new HttpEntity<>(body, headers);
          ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
          
          System.out.println(response.getBody());
        
      
        
          <?php
          $url = 'https://api-test.eximbay.com/v1/payments/verify';
          $data = '{
          "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
          }';
          
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, $url);
          curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo='));
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
          curl_setopt($ch, CURLOPT_POST, 1);
          
          curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
          $response  = curl_exec($ch);
          
          echo $response;
          curl_close($ch);
          ?>
        
      
        
   import requests
    import json
    
    url = "https://api-test.eximbay.com/v1/payments/verify"
    headers = {
    "Authorization": "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=",
    "Content-Type": "application/json"
    }
    
    request = {
    "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
    }
    response = requests.post(url, headers=headers, data=json.dumps(request))
    
    print(response.text)
        
      
        
  var request = require('request');
    var options = {
    'method': 'POST',
    'url': 'https://api-test.eximbay.com/v1/payments/verify',
    'headers': {
      'Authorization': 'Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
    "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
    })
    
    };
    request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
    });
        
      
          
   string uri = "https://api-test.eximbay.com/v1/payments/verify";
    string body = "{\n" +
    "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
    			        "}";
    
    WebClient webClient = new WebClient();
    webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
    webClient.Headers[HttpRequestHeader.Authorization] = "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=";
    webClient.Encoding = UTF8Encoding.UTF8;
    string responseJSON = webClient.UploadString(uri, body);
    
    Console.Write(responseJSON);
          
      
          
   val restTemplate =  RestTemplate()
    val headers = HttpHeaders()
    headers.add("Content-Type", "application/json")
    headers.add("Authorization", "Basic dGVzdF8xODQ5NzA1QzY0MkMyMTdFMEIyRDo=")
    
    var url = URI.create("https://api-test.eximbay.com/v1/payments/verify")
    
    val body = "{\n" +
    "data" : "currency=USD&card_number1=4111&transaction_date=20220927152250&card_number4=1111&mid=1849705C64&amount=100&access_country=KR&order_id=20220927152140&payment_method=P101&email=test@eximbay.com&ver=230&transaction_id=1849705C6420220927000016&param3=TEST&resmsg=Success.&card_holder=TESTP&rescode=0000&auth_code=309812&fgkey=2AE38D785E05E6AF57977328908C7CD84A273B3FE6C042D537A800B0CBC783EA&transaction_type=PAYMENT&pay_to=EXIMBAY.COM"
    		        "}"
    
    var entity = HttpEntity<String>(body, headers)
    var response = restTemplate.exchange(url, HttpMethod.POST, entity, String::class.java)
    
    println(response.body)
          
      

응답

응답코드로 0000을 받으면 결제 성공입니다.

                  
{
  "rescode": "0000",
  "resmsg": "Success",
}