7. Test Withdrawal (Transfer) Flow
The SDK's transfer() method opens the same overlay but in payout direction — the merchant sends crypto to the user's address. Unlike pay(), funds are not transferred immediately: a REQUESTED withdrawal is created in the dashboard, and a merchant admin must approve it (with 2FA) before the on-chain transfer fires.
7-1. Call SDK transfer()
await client.transfer({
price: 1,
unit: 'usd',
successUrl: '/withdrawal/success',
failUrl: '/withdrawal/fail',
onCreateInvoice: async (params) => {
const res = await fetch('/api/create-withdrawal', {
method: 'POST',
body: JSON.stringify(params),
});
const { withdrawalId } = await res.json();
return withdrawalId;
},
});
The callback receives receiver (recipient address) instead of sender. The server hits POST /api/invoices/withdrawals and returns withdrawalId. See Server Integration → Create Withdrawal for code examples.
7-2. Verify the Request in Dashboard
Dashboard → Project → 출금 요청 (Withdrawal Request)
A new row appears with status REQUESTED. The funds have not moved on-chain yet.
7-3. Admin Approves with 2FA
The merchant admin clicks Approve on the row → 2FA prompt → confirm.
This triggers the on-chain transfer from the project wallet to the receiver. Status moves REQUESTED → PENDING → CONFIRMED once mined.
7-4. Verify the On-chain Transfer
Dashboard → Project → 거래내역 (Transactions) — the withdrawal appears as type WITHDRAWAL with the resulting TX hash.
Click the TX hash to inspect on the block explorer.
Notes
- For testing, the merchant's project wallet must hold the token + native gas coin (e.g., USDC + ETH on Sepolia). Get it via the same faucets used for deposit testing, but send to the project wallet's address (visible on the project home).
- 2FA is required for approval — set up TOTP for the admin user beforehand.
- Bulk approval works the same way; multiple
REQUESTEDrows can be approved at once.