파트너정산 사용예제
파트너정산 API의 사용방법을 확인할 수 있습니다
가맹점 예시
커머스 마켓플레이스 가맹점에 대한 정산을 예시로 들어보겠습니다. 파트너(셀러) A 와 파트너(셀러) B가 있습니다. A 와 B에 적용될 대표 계약 정보는 아래와 같습니다.
A = 10% 중개 수수료, 정산주기 d+2, 매월 31일, 전 영업일 기준
B = 20% 중개 수수료, 정산주기 d+2, 매월 31일, 전 영업일 기준
- 계약생성 및 파트너 생성 및 대표계약 설정 는 관리자 콘솔에서 하실수 있으며 api로 하길 원하실경우 api 예시를 확인할 수 있습니다
주문 정산 예시
주문 정산 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
파라미터에 sharePolicyId
와 amount
(할인금액) 을 전달하시면 됩니다을
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"
}
}