파트너정산
사전 신청하기

파트너정산 사용예제

파트너정산 API의 사용방법을 확인할 수 있습니다

가맹점 예시

커머스 마켓플레이스 가맹점에 대한 정산을 예시로 들어보겠습니다. 파트너(셀러) A 와 파트너(셀러) B가 있습니다. A 와 B에 적용될 대표 계약 정보는 아래와 같습니다.

A = 10% 중개 수수료, 정산주기 d+2, 매월 31일, 전 영업일 기준

B = 20% 중개 수수료, 정산주기 d+2, 매월 31일, 전 영업일 기준

주문 정산 예시

주문 정산 1

주문금액 : 10,000원, 결제금액 : 10,000원 , 판매 파트너 : A, 정산시작일 (결제완료 시점): 2023-08-11

import requests
# v2 api 인증 토큰 발급 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
headers = {
        'Content-Type': 'application/json'
    }
# 발급받으신 API key를 입력해주세요
payload = {
        'apiKey': '[API_KEY]'
    }
 
response = requests.post('https://api.portone.io/login/api-key', headers=headers, json=payload)
token = response.json()['token']
 
# ... 결제 요청 및 결제 완료 로직 생략. 포트원 결제일경우 (참고: https://developers.portone.io/docs/ko/auth/guide/readme)
 
# 주문 정산 요청
 
orderTransferData ={
"partnerId": "partner_A", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_1", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
"orderAmount": 10000,
},
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False # 테스트 정산 여부
}
 
headers = {
"Authorization": f"Bearer {token}",
'Content-Type': 'application/json'
}
 
orderTransferResponse =requests.post('https://api.portone.io/platform/transfer/order', headers=headers, json=orderTransferData)
 
const axios = require("axios");
 
// v2 api 인증 토큰 발급 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
const token = "YOUR_TOKEN"; // Replace with your token
 
// 주문 정산 요청
const orderTransferData = {
  partnerId: "partner_A", // 파트너 A 파트너 아이디 등록 가정
  paymentId: "payment_1", // 포트원 결제시 가맹점 주문번호 (merchant_uid)입력
  orderDetail: {
    orderAmount: 10000,
  },
  settlementStartDate: null, // 결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
  isForTest: false, // 테스트 정산 여부
};
 
axios
  .post("https://api.portone.io/platform/transfer/order", orderTransferData, {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
  })
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("Error:", error.response.data);
  });

Response (snippet)

{'transfer':
 {'type': 'ORDER', 'id': '01H7J5DFHSGJ1M0433XZK9HGAB',
 'graphqlId': 'NjowMUg3SjVERkhTR0oxTTA0MzNYWks5SEdBQg==',
 'partner':
  {
    // 파트너 정보 생략 ...
    },
  'status': 'IN_PROCESS', // 정산 상태값. 정산 api 문서에서 보다 자세하게 확인하실 수 있습니다.
  'settlementDate': '2023-08-31', //정산일
  'settlementCurrency': 'KRW', //포트원 결제 통화를 따릅니다.
  'isForTest': False,
  'amount':{
      'settlement': 8900,//최종 정산금액
      'payment': 10000, //결제금액
      'order': 10000, //주문금액
      'platformFee': 1000,//중개 수수료 10%
      'platformFeeVat': 100, //중개수수료 부가세
      'additionalFee': 0, //추가 수수료
      'additionalFeeVat': 0, //추가 수수료 부가세
      'discount': 0, //할인금액
      'discountShare': 0 //할인금액 중 파트너가 부담하는 금액
      },
      'contract': //적용된 계약 정보. 파트너 A의 대표 계약이 적용됩니다.
      {
      "id": "contractA",
      "graphqlId": "NTpjb250cmFjdEE=",
      "memo": "contract A",
      "platformFee": {
        "type": "FIXED_RATE",
        "rate": 10000
      },
      'payment':
      {
      "id": "payment_1",
      "orderName": "string",
      "currency": "KRW",
      "method": {"card": {}},
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    'settlementStartDate': '2023-08-11', //기본값으로 결제 완료 시점을 따릅니다.
     'orderLines': [],
     'additionalFees': [],
     'discounts': []}}

주문 취소 정산 1

위 주문 정산건에 대해서 주문 취소가 일어났을때 주문취소 정산 등록하는 예시입니다.

취소금액 : 5,000원, 결제 취소금액 : 5,000원 , 판매 파트너 : A, 정산시작일 (결제 취소 완료 시점): 2023-08-12

# 결제 취소 후 취소아이디를 받아옵니다.
# 결제취소 아이디 (cancellation_id) 는 v2 api를 통해 발급 가능하며 #결제-취소(POST https://api.portone.io/v2/payments/{payment_id}/cancel),
# #결제내역-단건조회 (GET https://api.portone.io/v2/payments) api를 통해 받으실 수 있습니다.
# (참고: https://developers.portone.io/docs/ko/api-v2/payment/)
# 구현 생략.
 
# 주문취소 정산 요청
orderCancelTransferData ={
"partnerId": "partner_A",
"paymentId": "payment_1", # 기존 결제의 가맹점 주문번호 (merchant_uid)
"cancellationId": "cancellation_1", # 포트원 결제시 결제 취소 아이디 (참고: https://developers.portone.io/docs/ko/api-v2/payment/)
"orderDetail": {
"orderAmount": 5000,
},
"settlementStartDate": None, #결제취소 완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False # 테스트 정산 여부
}
 
headers = {
"Authorization": f"Bearer {token}",
'Content-Type': 'application/json'
}
 
orderCancelTransferResponse =requests.post('https://api.portone.io/platform/transfer/order', headers=headers, json=orderCancelTransferData)
const axios = require("axios");
 
// 결제 취소 후 취소아이디를 받아옵니다.
// 결제취소 아이디 (cancellation_id) 는 v2 api를 통해 발급 가능하며
// 결제-취소(POST https://api.portone.io/v2/payments/{payment_id}/cancel),
// 결제내역-단건조회 (GET https://api.portone.io/v2/payments) api를 통해 받으실 수 있습니다.
// (참고: https://developers.portone.io/docs/ko/api-v2/payment/)
// 구현 생략.
 
const token = "YOUR_TOKEN"; // Replace with your token
 
// 주문취소 정산 요청
const orderCancelTransferData = {
  partnerId: "partner_A",
  paymentId: "payment_1", // 기존 결제의 가맹점 주문번호 (merchant_uid)
  cancellationId: "cancellation_1", // 포트원 결제시 결제 취소 아이디 (참고: https://developers.portone.io/docs/ko/api-v2/payment/)
  orderDetail: {
    orderAmount: 5000,
  },
  settlementStartDate: null, // 결제취소 완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
  isForTest: false, // 테스트 정산 여부
};
 
axios
  .post(
    "https://api.portone.io/platform/transfer/order",
    orderCancelTransferData,
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
    }
  )
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("Error:", error.response.data);
  });

Response(snippet)

{'transfer':
 {'type': 'ORDER_CANCEL', 'id': '01H7J87XQ4JAS28RWZBC29YCJ1',
 'graphqlId': 'NjowMUg3Sjg3WFE0SkFTMjhSV1pCQzI5WUNKMQ==',
 'partner':
  {
    // 파트너 정보 생략 ...
    },
  'status': 'SCHEDULED', // 정산 상태값. 당시 8/12일이 미래 시점이어서 SCHEDULED로 잡혔습니다.
  'settlementDate': '2023-08-31',//정산일
  'settlementCurrency': 'KRW', //포트원 결제 통화를 따릅니다.
  'isForTest': False,
  'amount':{
      'settlement': 4450,//최종 정산취소금액
      'payment': 5000, //결제 취소 금액
      'order': 5000, //주문 취소 금액
      'platformFee': 500,//중개 수수료 10%
      'platformFeeVat': 100, //중개수수료 부가세
      'additionalFee': 0, //추가 수수료
      'additionalFeeVat': 0, //추가 수수료 부가세
      'discount': 0, //할인금액
      'discountShare': 0 //할인금액 중 파트너가 부담하는 금액
      },
      'contract':
      {
      //계약 정보 생략 ...
        },
      'payment':
      {
      "id": "payment_1",
      "orderName": "string",
      "currency": "KRW",
      "method": {"card": {}},
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    'settlementStartDate': '2023-08-12', //기본값으로 결제 취소 시점을 따릅니다.
     'orderLines': [],
     'additionalFees': [],
     'discounts': []
     'cancellation': // 결제 취소 정보
     {'id': 'cancellation_1',
     'cancelledAt': '2023-08-12T11:57:15.292Z'}
     }}

상품 정보를 통한 주문 정산 1

주문금액 : 14,000원, 상품 A 가격: 2,000 갯수: 5개, 상품 B 가격: 4,000 갯수: 1개 , 결제금액 : 14,000원

판매 파트너 : A, 정산시작일 (결제완료 시점): 2023-08-11

# 위 주문정산 1과 차이나는 부분만 기재하였습니다.
orderTransferData ={
  ## 생략 ...
  "orderDetail":{
    "orderLines":[
      {
        "product": {
          "id": "product_A", # 상품 아이디
          "name": "상품 A", # 상품 명
          "amount": 2000, # 상품 가격
          "tag": "과일", # 상품 태그 에시
        },
        "quantity": 5,
        "discounts": [], # 해당 상품에만 적용되는 할인정보
        "additionalFees": [], # 해당 상품에만 적용되는 추가 수수료 정보
      },
      {
        "product": {
          "id": "product_B", # 상품 아이시
          "name": "상품 B", # 상품 명
          "amount": 4000, # 상품 가격
          "tag": "과일", # 상품 태그 예시
        },
        "quantity": 1,
        "discounts": [], # 해당 상품에만 적용되는 할인정보
        "additionalFees": [], # 해당 상품에만 적용되는 추가 수수료 정보
      }
    ]
  }
  ## 생략 ...
  }
 
orderTransferResponse =requests.post('https://api.portone.io/platform/transfer/order', headers=headers, json=orderTransferData)
 
const axios = require("axios");
 
// 위 주문정산 1과 차이나는 부분만 기재하였습니다.
const orderTransferData = {
  // ... 생략 ...
  orderDetail: {
    orderLines: [
      {
        product: {
          id: "product_A", // 상품 아이디
          name: "상품 A", // 상품 명
          amount: 2000, // 상품 가격
          tag: "과일", // 상품 태그 에시
        },
        quantity: 5,
        discounts: [], // 해당 상품에만 적용되는 할인정보
        additionalFees: [], // 해당 상품에만 적용되는 추가 수수료 정보
      },
      {
        product: {
          id: "product_B", // 상품 아이시
          name: "상품 B", // 상품 명
          amount: 4000, // 상품 가격
          tag: "과일", // 상품 태그 예시
        },
        quantity: 1,
        discounts: [], // 해당 상품에만 적용되는 할인정보
        additionalFees: [], // 해당 상품에만 적용되는 추가 수수료 정보
      },
    ],
  },
  // ... 생략 ...
};
 
const headers = {
  "Content-Type": "application/json",
  Authorization: `Bearer ${token}`, // Replace with your token
};
 
axios
  .post("https://api.portone.io/platform/transfer/order", orderTransferData, {
    headers: headers,
  })
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("Error:", error.response.data);
  });

Response(snippet)

{
  "transfer": {
    "type": "ORDER",
    "id": "01H7MCX58SGYCNVN1CWY3HXM6D",
    "graphqlId": "NjowMUg3TUNYNThTR1lDTlZOMUNXWTNIWE02RA==",
    "partner": {
      // 파트너 정보 생략
    },
    "status": "IN_PROCESS",
    "settlementDate": "2023-08-31",
    "settlementCurrency": "KRW",
    "isForTest": false,
    "amount": {
      // 전체 주문건에 대한 정산정보
      "settlement": 12460, // 전체 주문건에 대한 정산 금액
      "payment": 14000,
      "order": 14000,
      "platformFee": 1400,
      "platformFeeVat": 140,
      "additionalFee": 0,
      "additionalFeeVat": 0,
      "discount": 0,
      "discountShare": 0
    },
    "contract": {
      //계약 정보 생략
    },
    "payment": {
      "id": "payment_1",
      "orderName": "string",
      "currency": "KRW",
      "method": { "card": {} },
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    "settlementStartDate": "2023-08-11",
    "orderLines": [
      // 상품별 주문 및 정산정보
      {
        "product": {
          "id": "product_A",
          "name": "상품 A",
          "amount": 2000,
          "tag": "과일"
        },
        "quantity": 5,
        "discounts": [],
        "additionalFees": [],
        "amount": {
          //상품 별 정산정보. 참고로 전체 주문에대한 할인 및 추가수수료 정보는 전체 주문건에 대한 정산정보에 포함됩니다.
          "settlement": 8900,
          "payment": 10000,
          "order": 10000,
          "platformFee": 1000,
          "platformFeeVat": 100,
          "additionalFee": 0,
          "additionalFeeVat": 0,
          "discount": 0,
          "discountShare": 0
        }
      },
      {
        "product": {
          "id": "product_B",
          "name": "상품 B",
          "amount": 4000,
          "tag": "과일"
        },
        "quantity": 1,
        "discounts": [],
        "additionalFees": [],
        "amount": {
          "settlement": 3560,
          "payment": 4000,
          "order": 4000,
          "platformFee": 400,
          "platformFeeVat": 40,
          "additionalFee": 0,
          "additionalFeeVat": 0,
          "discount": 0,
          "discountShare": 0
        }
      }
    ],
    "additionalFees": [], //전체 주문건에 대한 추가 수수료 정문
    "discounts": [] //전체 주문건에 대한 할인정보
  }
}

상품 정보를 통한 주문 취소 정산

주문취소 금액 : 4,000원, 취소 상품 A 가격: 2,000 취소 갯수: 2개, 결제 취소금액 4,000원

해당 경우에는 주문 취소 정산 1과 동일한 방식으로 취소되는 상품 정보를 orderLines 파라미터에 전달하시면 됩니다.

주문 : 정산 파트너가 1:N 일때

전체 주문금액 : 10,000원, 결제금액 10,000원, 판매 파트너 A, B

파트너 A 할당 주문금액 5,000원, 파트너 B 할당 주문금액 5,000원

정산 API는 현재 1명의 파트너에 대해 1개의 정산건 만 지원하고 있습니다. 따라서 단일 주문에 여러 파트너가 정산을 해야한다면 파트너의 주문금액 기준으로 정산건을 분리하여 별도의 정산건을 생성하셔야 합니다. 이는 orderLines 를 통한 정산API에도 동일하게 적용됩니다. (추후 상품관리 기능을 통해 각 상품별 정산 파트너를 지정할 수 있도록 개선할 예정입니다.)

# ... 결제 요청 및 결제 완료 로직 생략. 포트원 결제일경우 (참고: https://developers.portone.io/docs/ko/auth/guide/readme)
 
# 주문건에 대해서 주문금액 기준으로 직접 파트너별로 분리하여 정산건을 생성합니다.
 
orderTransferData_A ={
"partnerId": "partner_A", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_3", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
"orderAmount": 5000,
},
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False # 테스트 정산 여부
}
 
headers = {
"Authorization": f"Bearer {token}",
'Content-Type': 'application/json'
}
 
orderTransferResponse_A =requests.post('https://api.portone.io/platform/transfer/order', headers=headers, json=orderTransferData_A)
 
orderTransferData_B ={
"partnerId": "partner_B", # 파트너 B 파트너 아이디 등록 가정
"paymentId": "payment_3", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
"orderAmount": 5000,
},
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False # 테스트 정산 여부
}
 
orderTransferResponse_B =requests.post('https://api.portone.io/platform/transfer/order', headers=headers, json=orderTransferData_B)
 
const axios = require('axios');
 
// ... 결제 요청 및 결제 완료 로직 생략. 포트원 결제일경우 (참고: https://developers.portone.io/docs/ko/auth/guide/readme)
 
// 주문건에 대해서 주문금액 기준으로 직접 파트너별로 분리하여 정산건을 생성합니다.
 
const orderTransferData_A = {
  partnerId: "partner_A", // 파트너 A 파트너 아이디 등록 가정
  paymentId: "payment_3", // 포트원 결제시 가맹점 주문번호 (merchant_uid)
  orderDetail: {
    orderAmount: 5000
  },
  settlementStartDate: null, //결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
  isForTest: false // 테스트 정산 여부
};
 
const orderTransferData_B = {
  partnerId: "partner_B", // 파트너 B 파트너 아이디 등록 가정
  paymentId: "payment_3", // 포트원 결제시 가맹점 주문번호 (merchant_uid)
  orderDetail: {
    orderAmount: 5000
  },
  settlementStartDate: null, //결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
  isForTest: false // 테스트 정산 여부
};
 
const headers = {
  Authorization: `Bearer ${token}`,
  'Content-Type': 'application/json'
};
 
async function sendOrderTransfer(data) {
  try {
    const response = await axios.post('https://api.portone.io/platform/transfer/order', data, {
      headers: headers
    });
    return response.data;
  } catch (error) {
    console.error('Error sending order transfer:', error);
  }
}
 
(async () => {
  const orderTransferResponse_A = await sendOrderTransfer(orderTransferData_A);
  console.log(orderTransferResponse_A);
 
  const orderTransferResponse_B = await sendOrderTransfer(orderTransferData_B);
  console.log(orderTransferResponse_B);
})();
 

주문 정산 할인 반영

주문금액 : 10,000원, 할인금액 2000, 결제금액 : 8,000원 , 판매 파트너 : A, 정산시작일 (결제완료 시점): 2023-08-11 할인 정책: 파트너 분담율 50%

  • 할인 정책 생성 은 쿠폰과 포인트와 같은 할인 유형에 대해서 분담율 설정하신뒤 생성 하실 수 있습니다. 관리자 콘솔이나 api를 통해서 하실 수 있습니다.

discounts 파라미터에 sharePolicyIdamount (할인금액) 을 전달하시면 됩니다을

 
orderTransfer_payload = {
"partnerId": "partnerA", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_4", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
    "orderAmount": 10000, # 주문금액
  },
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False, # 테스트 정산 여부
"discounts": [ # 주문에 적용될 할인 정책. 리스트로써 할인 유형별 여러개를 전달하실 수 있습니다.
  {
    "sharePolicyId": "discount_2", # 할인 정책 아이디
    "amount": 2000 # 할인 금액
  }
]
}
 
orderTransfer_A = post_platform_api(token, 'platform/transfers/order', orderTransfer_payload)
const axios = require('axios');
 
const orderTransfer_payload = {
  partnerId: "partnerA", // 파트너 A 파트너 아이디 등록 가정
  paymentId: "payment_4", // 포트원 결제시 가맹점 주문번호 (merchant_uid)
  orderDetail: {
    orderAmount: 10000, // 주문금액
  },
  settlementStartDate: null, //결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
  isForTest: false, // 테스트 정산 여부
  discounts: [ // 주문에 적용될 할인 정책. 리스트로써 할인 유형별 여러개를 전달하실 수 있습니다.
    {
      sharePolicyId: "discount_2", // 할인 정책 아이디
      amount: 2000 // 할인 금액
    }
  ]
};
 
const headers = {
  Authorization: `Bearer ${token}`,
  'Content-Type': 'application/json'
};
 
async function post_platform_api(token, endpoint, payload) {
  try {
    const response = await axios.post(`https://api.portone.io/${endpoint}`, payload, {
      headers: headers
    });
    return response.data;
  } catch (error) {
    console.error('Error posting to platform API:', error);
  }
}
 
(async () => {
  const orderTransfer_A = await post_platform_api(token, 'platform/transfers/order', orderTransfer_payload);
  console.log(orderTransfer_A);
})();

Response(snippet)

{
  "transfer": {
    "type": "ORDER",
    "id": "01H7Q7WKY98R1TKM8XBHSQ1J6F",
    "graphqlId": "NjowMUg3UTdXS1k5OFIxVEtNOFhCSFNRMUo2Rg==",
    "partner": {
      // 파트너 정보 생략
    },
    "status": "IN_PROCESS",
    "settlementDate": "2023-08-31",
    "settlementCurrency": "KRW",
    "isForTest": false,
    "amount": { //주문건 정산 정보
      "settlement": 7900, // 정산금액
      "payment": 8000,
      "order": 10000,
      "platformFee": 1000,
      "platformFeeVat": 100,
      "additionalFee": 0,
      "additionalFeeVat": 0,
      "discount": 2000, // 적용된 할인금액
      "discountShare": 1000 //파트너가 부담할 할인금액 (할인 정책의 파트너 분담율이 50% 이기 때문에)
    },
    "contract": {
      // 계약 정보 생략
    },
    "payment": {
      "id": "payment_4",
      "orderName": "string",
      "currency": "KRW",
      "method": { "card": {} },
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    "settlementStartDate": "2023-08-11",
    "orderLines": [],
    "additionalFees": [],
    "discounts": [ //적용된 할인 정보
      {
        "sharePolicy": { //적용된 할인 정책
          "id": "discount_2",
          "graphqlId": "MjpkaXNjb3VudF8y",
          "partnerShareRate": 50000,
          "memo": "테스트 할인",
          "isHidden": false,
          "appliedAt": "2023-08-13T10:41:02.385833Z"
        },
        "amount": 2000,
        "shareAmount": 1000
      }
    ]
  }
}
 

주문 정산 상품 할인 반영

주문 전체가 아닌 특정 상품에대해서 할인 정책을 적용하고 싶으시면 orderLines 의 각 상품 항목의 discounts 파라미터에 전달하시면 됩니다.

주문 정산 추가 수수료 반영

주문금액 : 10,000원, 추가수수료(로켓배송) 2000, 결제금액 : 8,000원 , 판매 파트너 : A, 정산시작일 (결제완료 시점): 2023-08-11 추가 수수료 정책: 수수료율 5%, 부가세 파트너 부담

  • 추가수수료 정책 생성 은 로켓배송, 마케팅채널 수수료 등 특정 주문건에 적용되는 수수료 입니다. 관리자 콘솔이나 api를 통해서 하실 수 있습니다.

additionalFees 파라미터에 policyId 를 전달하시면 됩니다.

orderTransfer_payload = {
"partnerId": "partnerA", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_5", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
    "orderAmount": 10000, # 주문금액
  },
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False, # 테스트 정산 여부
"additionalFees": [ # 주문에 추가수수료 정책들. 리스트로써 여러개를 전달하실 수 있습니다.
  {
    "policyId": "addtional_fee_3", # 추가수수료 정책 아이디
  }
]
}
 
orderTransfer_A = post_platform_api(token, 'platform/transfers/order', orderTransfer_payload)
const axios = require('axios');
 
async function postPlatformApi(token, endpoint, payload) {
    const baseURL = 'https://api.portone.io/';
    const headers = {
        "Authorization": `Bearer ${token}`,
        'Content-Type': 'application/json'
    };
 
    try {
        const response = await axios.post(baseURL + endpoint, payload, { headers: headers });
        return response.data;
    } catch (error) {
        console.error("Error posting data:", error);
    }
}
 
const token = 'YOUR_TOKEN_HERE';
 
const orderTransferPayload = {
    "partnerId": "partnerA", // 파트너 A 파트너 아이디 등록 가정
    "paymentId": "payment_5", // 포트원 결제시 가맹점 주문번호 (merchant_uid)
    "orderDetail": {
        "orderAmount": 10000, // 주문금액
    },
    "settlementStartDate": null, //결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
    "isForTest": false, // 테스트 정산 여부
    "additionalFees": [ // 주문에 추가수수료 정책들. 리스트로써 여러개를 전달하실 수 있습니다.
        {
            "policyId": "addtional_fee_3", // 추가수수료 정책 아이디
        }
    ]
};
 
// Using the function
(async () => {
    const orderTransferA = await postPlatformApi(token, 'platform/transfers/order', orderTransferPayload);
    console.log(orderTransferA);
})();

Response(snippet)

{
    "transfer": {
        "type": "ORDER",
        "id": "01H7QEET738MFFY40NP4V7WW4V",
        "graphqlId": "NjowMUg3UUVFVDczOE1GRlk0ME5QNFY3V1c0Vg==",
        "partner": {
          //파트너 생략
        },
        "status": "IN_PROCESS",
        "settlementDate": "2023-08-31",
        "settlementCurrency": "KRW",
        "isForTest": false,
        "amount": { //주문건 정산 정보
            "settlement": 8350,
            "payment": 10000,
            "order": 10000,
            "platformFee": 1000,
            "platformFeeVat": 100,
            "additionalFee": 500, //추가수수료
            "additionalFeeVat": 50, //추가수수료 부가세
            "discount": 0,
            "discountShare": 0
        },
        "contract": {
          // 계약 생약
        },
        "payment": {
          "id": "payment_5",
          "orderName": "string",
          "currency": "KRW",
          "method": { "card": {} },
          "paidAt": "2023-08-11T08:21:01.241Z"
          },
        "settlementStartDate": "2023-08-11",
        "orderLines": [],
        "additionalFees": [ // 적용된 추가수수료 정책 정보
            {
                "policy": {
                    "id": "addtional_fee_3",
                    "graphqlId": "MzphZGR0aW9uYWxfZmVlXzM=",
                    "fee": {
                        "type": "FIXED_RATE",
                        "rate": 5000
                    },
                    "memo": "테스트 추가수수료",
                    "vatPayer": "PARTNER",
                    "isHidden": false,
                    "appliedAt": "2023-08-13T12:31:50.822913Z"
                },
                "amount": 500,
                "vat": 50
            }
        ],
        "discounts": []
    }
}
 

주문 정산 상품별 추가 수수료 반영

주문 전체가 아닌 특정 상품에대해서 할인 정책영 적용하고 싶으시면 orderLines 의 각 상품 항목의 additionalFees 파라미터에 전달하시면 됩니다.

포트원 결제가 아닌 주문 정산

externalPaymentDetail 에 결제정보를 전달주시면 됩니다! payment_id 는 가맹점 고유 주문번호로 전달해주시면 됩니다.

orderTransfer_payload = {
"partnerId": "partnerA", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_5", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
    "orderAmount": 10000, # 주문금액
  },
"settlementStartDate": None, #결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
"isForTest": False, # 테스트 정산 여부
"externalPaymentDetail": { # 포트원 결제가 아닌 주문 정산시 전달하시면 됩니다.
    "currency": "KRW", # 결제 통화 정보
    "orderName": "테스트 주문",
    "paidAt": "2023-08-11T08:21:01.241Z", # 결제 완료 시점. settlementStartDate을 전달하지 않으실경우 꼭 전달하셔야 됩니다.
    "method": {
      "card": {},
    }
  },
"additionalFees": [ # 주문에 추가수수료 정책들. 리스트로써 여러개를 전달하실 수 있습니다.
  {
    "policyId": "addtional_fee_3", # 추가수수료 정책 아이디
  }
]
}
 
orderTransfer_A = post_platform_api(token, 'platform/transfers/order', orderTransfer_payload)
 
// Assuming you're using Axios for HTTP requests in Node.js. If not, you can replace it with your preferred HTTP client.
const axios = require('axios');
 
const orderTransferPayload = {
    partnerId: "partnerA", // 파트너 A 파트너 아이디 등록 가정
    paymentId: "payment_5", // 포트원 결제시 가맹점 주문번호 (merchant_uid)
    orderDetail: {
        orderAmount: 10000, // 주문금액
    },
    // 결제완료 시점으로 등록을 원하실 경우 전달하지 않으셔도 됩니다.
    settlementStartDate: null,
    isForTest: false, // 테스트 정산 여부
    externalPaymentDetail: { // 포트원 아닌 결제건 정보
        currency: "KRW",
        orderName: "테스트 주문",
        paidAt: "2023-08-11T08:21:01.241Z",
        method: {
            card: {}
        }
    },
    additionalFees: [ // 주문에 추가수수료 정책들. 리스트로써 여러개를 전달하실 수 있습니다.
        {
            policyId: "addtional_fee_3", // 추가수수료 정책 아이디
        }
    ]
};
 
// Define the `postPlatformApi` function if you haven't already.
async function postPlatformApi(token, endpoint, data) {
    try {
        const response = await axios.post(endpoint, data, {
            headers: {
                Authorization: `Bearer ${token}`
            }
        });
        return response.data;
    } catch (error) {
        console.error("Error posting to API:", error);
        return null;
    }
}
 
const token = "YOUR_TOKEN_HERE"; // Replace with your token
const orderTransferA = postPlatformApi(token, 'platform/transfers/order', orderTransferPayload);
 

Response(snippet)

{
  "transfer": {
    "type": "ORDER",
    "id": "01H7QEET738MFFY40NP4V7WW4V",
    "graphqlId": "NjowMUg3UUVFVDczOE1GRlk0ME5QNFY3V1c0Vg==",
    "partner": {
      //파트너 정보 생략
    },
    "status": "IN_PROCESS",
    "settlementDate": "2023-08-31",
    "settlementCurrency": "KRW",
    "isForTest": false,
    "amount": {
      "settlement": 8350,
      "payment": 10000,
      "order": 10000,
      "platformFee": 1000,
      "platformFeeVat": 100,
      "additionalFee": 500,
      "additionalFeeVat": 50,
      "discount": 0,
      "discountShare": 0
    },
    "contract": {
      //계약 정보 생략
    },
    "payment": {
      "type": "EXTERNAL", //포트원 결제가 아닐경우 결제일 경우 EXTERNAL로 표기됩니다.
      "id": "payment_5",
      "orderName": "테스트 주문",
      "currency": "KRW",
      "method": {
        "type": "CARD"
      },
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    "settlementStartDate": "2023-08-11",
    "orderLines": [],
    "additionalFees": [
      // 추가수수료 정보 생략
      ],
    "discounts": []
  }
}
 

정산 시작일을 지정해서 보내는 경우

정산고려를 배달완료, 수강오픈, 이용완료 등의 시점부터 하고 싶으시면 settlementStartDate 파라미터에 해당시점을 'YYYY-MM-DD'형식으로 전달하시면 됩니다.

해당 시점이 정해졌을때 정산 api를 호출하시면 됩니다.

orderTransfer_payload = {
"partnerId": "partnerA", # 파트너 A 파트너 아이디 등록 가정
"paymentId": "payment_6", # 포트원 결제시 가맹점 주문번호 (merchant_uid)
"orderDetail": {
    "orderAmount": 10000, # 주문금액
  },
"settlementStartDate": '2023-09-01', # 배송완료 시점 (예시)
"isForTest": False, # 테스트 정산 여부
}
 
orderTransfer_A = post_platform_api(token, 'platform/transfers/order', orderTransfer_payload)
const axios = require('axios');
 
// Define payload
const orderTransfer_payload = {
  partnerId: "partnerA",  // 파트너 A 파트너 아이디 등록 가정
  paymentId: "payment_6",  // 포트원 결제시 가맹점 주문번호 (merchant_uid)
  orderDetail: {
    orderAmount: 10000  // 주문금액
  },
  settlementStartDate: '2023-09-01',  // 배송완료 시점 (예시)
  isForTest: false,  // 테스트 정산 여부
};
 
// Define function for making the API request
async function post_platform_api(token, endpoint, data) {
  try {
    const response = await axios.post(endpoint, data, {
      headers: {
        Authorization: `Bearer ${token}`
      }
    });
    return response.data;
  } catch (error) {
    console.error("Error making API request:", error);
  }
}
 
// Make the request
const token = "YOUR_TOKEN_HERE";
const endpoint = 'https://api.example.com/platform/transfers/order';  // Replace with your actual endpoint
const orderTransfer_A = await post_platform_api(token, endpoint, orderTransfer_payload);
console.log(orderTransfer_A);
 

Response(snippet)

{
  "transfer": {
    "type": "ORDER",
    "id": "01H7QHWNSNHCT9RF9GYKSKXRBZ",
    "graphqlId": "NjowMUg3UUhXTlNOSENUOVJGOUdZS1NLWFJCWg==",
    "partner": {
      //파트너 정보 생략
    },
    "status": "SCHEDULED", // 정산 시작일이 미래이므로 SCHEDULED 상태로 표기됩니다.
    "settlementDate": "2023-09-27", //설날을 고려하여 그 전 영업일이 됐습니다.
    "settlementCurrency": "KRW",
    "isForTest": false,
    "amount": {
      "settlement": 8900,
      "payment": 10000,
      "order": 10000,
      "platformFee": 1000,
      "platformFeeVat": 100,
      "additionalFee": 0,
      "additionalFeeVat": 0,
      "discount": 0,
      "discountShare": 0
    },
    "contract": {
      // 계약 정보 생약
      },
    "payment": {
      "id": "payment_6",
      "orderName": "string",
      "currency": "KRW",
      "method": {"card": {}},
      "paidAt": "2023-08-11T08:21:01.241Z"
    },
    "settlementStartDate": "2023-09-01",
    "orderLines": [],
    "additionalFees": [],
    "discounts": []
  }
}
 

계약 예시

계약 생성하기

계약 1 : 10% 중개 수수료, 정산주기 d+2, 매월 31일, 전 영업일 기준

# v2 api 인증 토큰 발급 생략 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
 
contract_payload = {
  "platformFee": {"fixedRate": 10000}, # 10% 수수료. 료율 표시 기준은 1/100000 입니다. 따라서 소수점 5자리까지 표시 가능합니다.
  "platformFeeVatPayer": "PARTNER", # 부가세 부담 여부. 파트너 부담("PARTNER"), 파트너 미부담("MERCHANT") 가 있습니다.
  "id": "contractA",
  "memo": "contract A",
  "settlementCycle": { #정산주기
    "lagDays": 2, #정산 지연일 (d+n)일
    "datePolicy": "HOLIDAY_BEFORE", # 전 영업일 기준
    "method": { #'daily','weekly','monthly' 'manualDates' 중 하나를 선택하셔야 합니다.
      'monthly':{"daysOfMonth":[31] # 매월 31일. 31일은 월말 기준으로 합니다.
      }
      }}
  }
 
 
contract_A = post_platform_api(token, 'platform/contracts/', contract_payload)
 
const axios = require('axios');
 
// 10% 수수료. 료율 표시 기준은 1/100000 입니다. 따라서 소수점 5자리까지 표시 가능합니다.
const contract_payload = {
  platformFee: { fixedRate: 10000 },
  // 부가세 부담 여부. 파트너 부담("PARTNER"), 파트너 미부담("MERCHANT") 가 있습니다.
  platformFeeVatPayer: "PARTNER",
  id: "contractA",
  memo: "contract A",
  //정산주기
  settlementCycle: {
    //정산 지연일 (d+n)일
    lagDays: 2,
    // 전 영업일 기준
    datePolicy: "HOLIDAY_BEFORE",
    // 'daily','weekly','monthly' 'manualDates' 중 하나를 선택하셔야 합니다.
    method: {
      // 매월 31일. 31일은 월말 기준으로 합니다.
      monthly: { daysOfMonth: [31] }
    }
  }
};
 
async function post_platform_api(token, endpoint, payload) {
  const baseURL = "YOUR_API_BASE_URL";  // replace with your actual API base URL
 
  try {
    const response = await axios.post(`${baseURL}/${endpoint}`, payload, {
      headers: {
        Authorization: `Bearer ${token}`  // assuming a Bearer token for authentication
      }
    });
 
    return response.data;
  } catch (error) {
    console.error('Error posting data:', error);
  }
}
 
const token = "YOUR_ACCESS_TOKEN";  // replace with your actual token
post_platform_api(token, 'platform/contracts/', contract_payload).then(response => {
  const contract_A = response;
  console.log(contract_A);
});
 

Response(snippet)

{
  "contract": {
    "id": "contractA",
    "graphqlId": "NTpjb250cmFjdEE=",
    "memo": "contract A",
    "platformFee": {
      "type": "FIXED_RATE",
      "rate": 10000
    },
    "settlementCycle": {
      "lagDays": 2,
      "datePolicy": "HOLIDAY_BEFORE",
      "method": {
        "type": "MONTHLY",
        "daysOfMonth": [31]
      }
    },
    "platformFeeVatPayer": "PARTNER",
    "isHidden": false,
    "appliedAt": "2023-08-11T11:18:52.944447Z" // 업데이트 된 순간을 뜻합니다. 추후 해당 계약에대한 업데이트 가 있을때 해당 시점을 보여줍니다.
  }
}

파트너 예시

파트너 생성하기

# v2 api 인증 토큰 발급 생략 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
 
# 파트너 생성 예시
partner_payload = {
  "id": "partnerA", # 파트너 아이디
  "name": "파이썬 강사", # 파트너 이름 및 사업자명
  "email": "kjnkyj12@gmail.com",
  "businessRegistrationNumber": "1178178260", #파트너 사업자 등록번호. 필수는 아닙니다
  "account": {
    "bank": "SHINHAN", # 파트너 계좌 은행. 국내 은행일경우 영문 대문자로 보내줘야 하며 이에대한 enum 값을 api문서에서 확인 가능합니다.
    "currency": "KRW", # 계좌 입금 통화
    "number": "10358907249", # 계좌 번호
    "holder": "김준일" # 예금주
  },
  "defaultContractId": "contractA", # 해당 파트너에게 적용하길 원하는 대표계약
  "memo": "잭슨 테스트 예시문",
  "tags": [
    "파이썬"
  ]
}
 
partner_A = post_platform_api(token, 'platform/partners', partner_payload)
const axios = require('axios');
 
// Define the payload
const partnerPayload = {
  "id": "partnerA", // 파트너 아이디
  "name": "파이썬 강사", // 파트너 이름 및 사업자명
  "email": "kjnkyj12@gmail.com",
  "businessRegistrationNumber": "1178178260", // 파트너 사업자 등록번호. 필수는 아닙니다
  "account": {
    "bank": "SHINHAN", // 파트너 계좌 은행. 국내 은행일경우 영문 대문자로 보내줘야 하며 이에 대한 enum 값을 api문서에서 확인 가능합니다.
    "currency": "KRW", // 계좌 입금 통화
    "number": "10358907249", // 계좌 번호
    "holder": "김준일" // 예금주
  },
  "defaultContractId": "contractA", // 해당 파트너에게 적용하길 원하는 대표계약
  "memo": "잭슨 테스트 예시문",
  "tags": ["파이썬"]
};
 
// Make a POST request
const postPlatformApi = async (token, url, payload) => {
  try {
    const headers = {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
 
    const response = await axios.post(url, payload, { headers: headers });
    console.log('Response:', response.data);
    return response.data;
  } catch (error) {
    console.error('Error posting data:', error);
  }
};
 
const token = 'YOUR_TOKEN'; // Replace with your actual token
const url = 'YOUR_API_ENDPOINT/platform/partners'; // Replace with your actual API endpoint
const partnerA = postPlatformApi(token, url, partnerPayload);
 

Response(snippet)

{
  "partner": {
    "id": "partnerA",
    "graphqlId": "NDpwYXJ0bmVyQQ==",
    "name": "파이썬 강사",
    "email": "kjnkyj12@gmail.com",
    "businessRegistrationNumber": "1178178260",
    "account": {
      "bank": "SHINHAN",
      "currency": "KRW",
      "number": "10358907249",
      "holder": "김준일",
      "status": "VERIFIED" // 계좌 인증 상태
    },
    "status": "APPROVED",
    "defaultContractId": "contractA",
    "memo": "잭슨 테스트 예시문",
    "tags": [
      "파이썬"
    ],
    "isHidden": false,
    "appliedAt": "2023-08-11T11:19:58.829787Z"
  }
}

할인 예시

할인 생성하기

할인 정책 1 : 할인 금액 50% 파트너 분담

# v2 api 인증 토큰 발급 생략 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
 
# 할인 정책 생성 예시
 
discount_payload = {
  "id": "discount_2", #할인 아이디
  "partnerShareRate": 50000, # 10^5기준, 50% 분담
  "memo": "테스트 할인"
}
 
discount_2 = post_platform_api(token, 'platform/discount-share-policies', discount_payload)
 
const axios = require('axios');
 
// v2 API 인증 토큰 발급 생략 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
 
// 할인 정책 생성 예시
 
const discount_payload = {
  id: "discount_2", //할인 아이디
  partnerShareRate: 50000, // 10^5기준, 50% 분담
  memo: "테스트 할인"
};
 
async function post_platform_api(token, endpoint, data) {
  const baseURL = 'https://api.baseurl.com/'; // Replace with the correct base URL
  const headers = {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json'
  };
 
  try {
    const response = await axios.post(baseURL + endpoint, data, { headers });
    return response.data;
  } catch (error) {
    console.error('Error posting data:', error);
  }
}
 
const token = 'YOUR_TOKEN_HERE'; // Replace with your actual token
post_platform_api(token, 'platform/discount-share-policies', discount_payload)
  .then(data => {
    console.log('Discount created:', data);
  });
 

Response(snippet)

{
  "discountSharePolicy":{
    "id": "discount_2",
    "graphqlId": "MjpkaXNjb3VudF8y",
    "partnerShareRate": 50000,
    "memo": "테스트 할인",
    "isHidden": false,
    "appliedAt": "2023-08-13T10:41:02.385833Z"
  }
}

추가수수료 예시

추가수수료 생성하기

추가수수료 정책 1 : 추가수수료 5% 파트너 분담

 
# v2 api 인증 토큰 발급 생략 (참고: https://developers.portone.io/docs/ko/api-v2/authorization)
 
# 추가수수료 정책 생성 예시
additionalfees_payload = {
  "id": "addtional_fee_3",
  "fee": {
    "fixedRate": 5000,
  },
  "memo": "테스트 추가수수료",
  "vatPayer": "PARTNER"
}
 
additionalfees_1 = post_platform_api(token, 'platform/additional-fee-policies', additionalfees_payload)
 

Response(snippet)

{"additionalFeePolicy":
  {
  "id": "addtional_fee_3",
  "graphqlId": "MzphZGR0aW9uYWxfZmVlXzM=",
  "fee.type": "FIXED_RATE",
  "fee.rate": 5000,
  "memo": "테스트 추가수수료",
  "vatPayer": "PARTNER",
  "isHidden": false,
  "appliedAt": "2023-08-13T12:31:50.822913Z"
}
}