yupenpay API Documentation
Open integration guide for all website and app developers. This document describes how to integrate payment collection, refunds, reconciliation and webhooks with yupenpay — covering setup, signature authentication, API calls and code examples to get you integrated within the hour.
01Overview
yupenpay is a payment orchestration platform for merchants, aggregating licensed acquiring channels and providing a unified collection API to websites and apps. Funds are settled directly by the acquiring institution to the merchant — the platform never holds customer funds.
Capabilities
- Unified collection: one integration for credit cards, local wallets, bank transfers and local payments
- Refund management: original-route refunds with partial refund and refund query support
- Reconciliation: generate statements per merchant and time period with automatic reconciliation
- Webhooks: async payment result notifications with signature verification
- Dual environments: sandbox testing + live production, with isolated keys
Who is this for
Any website, web app, mobile app (iOS / Android) or desktop application that needs online payment collection can integrate via this document. Protocol is HTTP/HTTPS + JSON, supported by all mainstream languages.
02Quick Start
Before you start
merchantNo and merchantId.tp_sk_... and a live key tp_sk_live_....Minimal example
The minimal create-payment request (sandbox environment):
bash / curlcurl -X POST "https://yupeng.store/api/transactions/create" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "merchantId": "m1", "amount": 2580.00, "currency": "USD", "channelId": "ch1", "description": "Order #ORD20241207001", "customerEmail": "buyer@example.com" }'
A successful call returns a transaction whose status is success. When no key is configured the system automatically falls back to simulation mode for easy development.
03Authentication
Get an access token
The platform uses Bearer Token authentication. First call the login endpoint to obtain a token:
bashcurl -X POST "https://yupeng.store/api/auth/login" \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin123"}'
Example response:
json{ "success": true, "data": { "user": { "username": "admin", "name": "Administrator", "role": "Super Admin" }, "token": "demo_token_1720000000000" } }
Authorization header
All endpoints except login must carry the token in the request header:
httpAuthorization: Bearer <ACCESS_TOKEN>
Unified response structure
All endpoints return a unified JSON structure:
json{ "success": true, // success flag "data": { }, // business data (optional) "message": "Operation succeeded", // message (optional) "error": "Error description" // failure reason (optional) }
Auth endpoints
Login with username and password to obtain an access token.
| Parameter | Type | Description |
|---|---|---|
username | string | Login account |
password | string | Login password |
Get the current logged-in user info (requires Bearer token).
Log out.
04Payment Flow
A complete integration involves "create payment → pay → webhook → query / refund". The recommended flow:
/api/transactions/createorderNoCreate payment
Create a payment transaction. The system calls the real acquiring API when keys are configured; otherwise it falls back to simulated success for integration testing.
| Parameter | Type | Required | Description |
|---|---|---|---|
merchantId | string | Yes | Merchant ID, must be an approved merchant |
amount | number | Yes | Transaction amount |
currency | string | No | Currency, default USD |
channelId | string | No | Acquiring channel ID, default ch1 (credit card) |
description | string | No | Transaction note / order description |
customerEmail | string | No | Customer email |
Example response
json{ "success": true, "data": { "id": "tx_a1b2c3", "orderNo": "TX202412071532001", "merchantName": "Star Cross-Border Trading", "amount": 2580.00, "fee": 15.48, "netAmount": 2564.52, "currency": "USD", "status": "success", "channelName": "yupenpay - Credit Card", "paymentMethod": "Credit Card", "tagadaPaymentId": "pay_mock_xxxxxxxx", "createdAt": "2026-10-17 06:56:21" }, "meta": { "mode": "mock", "env": "sandbox" } }
Transaction status
| Status | Description |
|---|---|
success | Payment succeeded, funds enter the settlement flow |
failed | Payment failed, channel returned an error |
pending | Processing, awaiting channel confirmation |
refunding | Refund issued, awaiting original-route return |
refunded | Refund completed, funds returned |
disputed | Cardholder dispute / chargeback in progress |
Query transactions
Query transaction list and details by order or merchant:
Transaction list with filters.
| Query param | Type | Description |
|---|---|---|
status | string | Filter by status, e.g. success, failed, refunded |
channelId | string | Filter by channel |
merchantId | string | Filter by merchant |
keyword | string | Order number / merchant name keyword |
Response: data.list (transaction array), data.total (total count).
Transaction detail — returns transaction, refund record, dispute record and status timeline (data.transaction / data.refund / data.dispute / data.timeline).
05API Reference
All available endpoints by module. Except login, all require Authorization: Bearer <token>.
Dashboard statistics
Core operational overview. Returns todayAmount, todayOrderCount, successRate, todaySettlementAmount, merchantCount and period-over-period changes.
7-day transaction trend; data is an array of { date, amount, orderCount }.
Channel share; returns id / channelName / amount / ratio / color.
Status distribution (success / failed / refund / dispute, etc.).
Recent transactions (latest 8).
Top merchants by cumulative volume.
Merchant management
Merchant list, filter by status / keyword, returns data.list / data.total.
Merchant detail with merchant, its transactions, refunds, settlements and stats.
Create a merchant. Params name, contact, phone, email, businessLicense; created in pending review.
Merchant review. Params action (approve / reject), reason (rejection reason).
Enable / disable a merchant.
Acquiring channels
Channel list with health status, fees and today's volume.
Enable / disable a channel.
Update channel fee. Param rate (decimal, e.g. 0.006 = 0.6%).
Refunds & disputes
Issue a refund. Only success transactions can be refunded; params amount (≤ transaction amount), reason. Live mode submits to the acquiring institution; mock mode succeeds immediately.
Refund list, filter by status / keyword.
Dispute list.
Handle a dispute. Params action (appeal / accept), comment.
Settlements & reconciliation
Settlement batch list, returns data.list / data.total.
Settlement batch detail with merchantSettlements.
Trigger reconciliation (only for pending batches).
System settings
Platform config (without key values): platformName, companyName, serviceEmail, servicePhone, address, activeEnv, sandboxConfigured, liveConfigured.
Save platform basic info.
Configure channel keys. Params sandboxKey, liveKey, activeEnv (sandbox / live).
Test channel connection. Param env, returns connected.
Fee rules list.
Update a channel's fee.
Change password. Params oldPassword, newPassword (≥ 6 chars).
06Webhooks
Payment / refund results are pushed to your registered URL asynchronously via webhook, to update order status in real time.
Flow
https://your-site.com/api/pay/callback.POST to your URL, including payment / refund result and signature.orderNo; deduplicate by eventId to avoid double entry.HTTP 200 on success; otherwise delivery is considered failed and retried.Example event
json{ "eventId": "evt_20261017_001", "eventType": "payment.succeeded", // payment succeeded "orderNo": "TX202412071532001", "transactionId": "tx_a1b2c3", "amount": 2580.00, "currency": "USD", "status": "success", "completedAt": "2026-10-17 06:56:21", "signature": "<HMAC-SHA256 signature>" }
eventTypes instead of allowing them through.Supported event types
| eventType | Meaning |
|---|---|
payment.succeeded | Payment succeeded |
payment.failed | Payment failed |
refund.succeeded | Refund succeeded |
dispute.created | Dispute / chargeback created |
07Statements
The system generates two types of statements for merchants / customers to reconcile. Both are printable and can be saved as PDF:
Single payment receipt: generates a collection receipt for a successful transaction, including platform header, amount, merchant, payment method, order number, card number and time — for customers to keep.
Merchant summary statement: aggregates all successful transactions by merchant and time range (from / to), returning count, total amount, fees, net amount and details.
08Error Codes
On error the API returns a non-2xx status and an error field with a description. Common codes:
| Status | Description | Suggested action |
|---|---|---|
400 | Invalid request params / business validation failed | Check params, e.g. merchant not reviewed, channel unavailable, refund exceeds amount |
401 | Not authenticated / invalid token | Re-login to get a token, or check the Authorization header |
404 | Resource or endpoint not found | Check the resource ID and endpoint path |
500 | Internal server error | Retry later, or contact platform support |
Common business errors (error field)
| error | Meaning |
|---|---|
Invalid username or password | Login credentials incorrect |
Merchant not found / not approved | merchantId invalid or merchant cannot transact |
Channel unavailable | channelId invalid or channel disabled |
Only successful transactions can be refunded | Refund precondition not met |
Refund amount cannot exceed transaction amount | Partial refund exceeds limit |
This batch cannot be reconciled | Settlement batch already reconciled |
Sandbox / live key not configured | Acquiring key not set; currently in mock mode |
09Code Examples
Minimal "login → create payment" examples (sandbox environment).
Node.js (fetch)
javascriptconst BASE = 'https://yupeng.store'; async function login() { const res = await fetch(`${BASE}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: 'admin123' }), }).then(r => r.json()); return res.data.token; } async function createPayment(token) { const res = await fetch(`${BASE}/api/transactions/create`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ merchantId: 'm1', amount: 2580, currency: 'USD' }), }).then(r => r.json()); return res.data; } login().then(token => createPayment(token)).then(console.log);
Python (requests)
pythonimport requests BASE = "https://yupeng.store" def login(): r = requests.post(f"{BASE}/api/auth/login", json={"username": "admin", "password": "admin123"}) return r.json()["data"]["token"] def create_payment(token): r = requests.post(f"{BASE}/api/transactions/create", json={"merchantId": "m1", "amount": 2580, "currency": "USD"}, headers={"Authorization": f"Bearer {token}"}) return r.json() print(create_payment(login()))
PHP
php<?php $base = 'https://yupeng.store'; $token = json_decode(file_get_contents($base.'/api/auth/login', false, stream_context_create(['http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => json_encode(['username'=>'admin', 'password'=>'admin123']), ]])), true)['data']['token']; $res = json_decode(file_get_contents($base.'/api/transactions/create', false, stream_context_create(['http' => [ 'method' => 'POST', 'header' => "Authorization: Bearer {$token}\r\nContent-Type: application/json", 'content' => json_encode(['merchantId'=>'m1', 'amount'=>2580, 'currency'=>'USD']), ]])), true); var_dump($res); ?>
Java (OkHttp)
javaString base = "https://yupeng.store"; OkHttpClient client = new OkHttpClient(); String login() throws IOException { Request req = new Request.Builder().url(base + "/api/auth/login") .post(RequestBody.create( "{\"username\":\"admin\",\"password\":\"admin123\"}", MediaType.parse("application/json"))) .build(); return JSON.parseObject(client.newCall(req).execute().body().string()) .getJSONObject("data").getString("token"); } String createPayment(String token) throws IOException { Request req = new Request.Builder().url(base + "/api/transactions/create") .header("Authorization", "Bearer " + token) .post(RequestBody.create( "{\"merchantId\":\"m1\",\"amount\":2580,\"currency\":\"USD\"}", MediaType.parse("application/json"))) .build(); return client.newCall(req).execute().body().string(); }
10FAQ
1. How do I test without real charges?
Leave the channel key unconfigured. The system automatically enters mock mode — payments and refunds return success, perfect for development. Configure a real key to switch to live collection.
2. What is the difference between sandbox and live?
Sandbox is for testing with sandbox keys; live is for real online collection with live keys. The two key sets are isolated and independent.
3. How long does a refund take?
Mock mode succeeds immediately; live mode is returned via the original route by the acquiring institution, usually within a few business days.
4. I did not receive a webhook. What now?
Confirm the webhook URL is registered and publicly reachable. The platform retries deliveries that do not return HTTP 200. You can also call the transaction query API to verify status.
5. How do I generate a statement for a merchant?
Single receipt: Transactions → successful transaction → statement. Merchant summary: Merchants → merchant → statement (optional date range). Both support print / save as PDF.
6. What qualifications are required to integrate?
This is a demo / integration document using the demo account (admin/admin123). For production, complete merchant identity and business verification through the platform.