高级功能 Web SDK
Yuno Web SDK的高级配置选项和自定义集成。
替代安装方案
基本流程使用 mountCheckout() 用于自动显示支付方式。如需更多控制选项,请使用以下替代方案:
自定义支付方式选择(mountCheckoutLite())
mountCheckoutLite())控制要显示的支付方式:
// 1. Fetch available methods from backend
const methods = await fetch('/api/payment-methods').then(r => r.json());
// 2. Display methods in your custom UI
// 3. Mount selected payment method
yuno.mountCheckoutLite({
paymentMethodType: selectedMethod, // 'CARD', 'PIX', etc.
vaultedToken: null // or saved token
});
// 4. Still need startPayment()
document.querySelector('#pay-button').addEventListener('click', () => {
yuno.startPayment();
});Google Pay 与 Apple Pay 支持 Lite 版本:
await yuno.mountExternalButtons([
{
paymentMethodType: 'GOOGLE_PAY',
elementSelector: '#google-pay-button'
},
{
paymentMethodType: 'APPLE_PAY',
elementSelector: '#apple-pay-button'
}
]);简化流程 (mountSeamlessCheckout())
mountSeamlessCheckout())类似于 mountCheckoutLite() 但通过自动创建付款:
// Use startSeamlessCheckout instead of startCheckout
yuno.startSeamlessCheckout({
// Same configuration
});
// Mount
yuno.mountSeamlessCheckout({
paymentMethodType: 'CARD'
});
// Still need startPayment()
document.querySelector('#pay-button').addEventListener('click', () => {
yuno.startPayment();
});注册(保存卡片)
付款时节省
yuno.startCheckout({
checkoutSession: session.id,
elementSelector: '#payment-container',
countryCode: 'US',
card: {
cardSaveEnable: true // Shows "Save card" checkbox
},
async yunoCreatePayment(token) {
await fetch('/api/payment/create', {
method: 'POST',
body: JSON.stringify({
token,
vault_on_success: true // Save card after successful payment
})
});
yuno.continuePayment();
}
});单独注册
// Create customer session on backend
const customerSession = await fetch('/api/customer/session', {
method: 'POST',
body: JSON.stringify({ customer_id: 'cus_123' })
}).then(r => r.json());
// Initialize enrollment
yuno.startEnrollment({
customerSession: customerSession.id,
countryCode: 'US',
async yunoEnrolled(vaultedToken) {
console.log('Card saved:', vaultedToken);
}
});
// Mount enrollment form
yuno.mountEnrollment();拱顶Token
// Use saved card
yuno.mountCheckout({
vaultedToken: 'vtok_saved_card_123'
});
// Still need startPayment()
document.querySelector('#pay-button').addEventListener('click', () => {
yuno.startPayment();
});自定义用户界面(无头集成)
当您需要完全掌控每个用户界面元素、构建高度定制的结账体验,或拥有开发定制界面的资源时,可创建完全自定义的支付表单并实现全面的用户界面控制。Yuno仅处理令牌化功能。
实施
1.Initialize
const yuno = await Yuno.initialize('your-public-key');
const apiClientPayment = yuno.apiClientPayment({
country_code: "US",
checkout_session: "checkout_session_id"
});2. 创建您的自定义表单
<form id="custom-payment-form">
<input id="card-number" placeholder="Card Number" />
<input id="expiry" placeholder="MM/YY" />
<input id="cvv" placeholder="CVV" />
<input id="cardholder" placeholder="Cardholder Name" />
<button type="submit">Pay</button>
</form>3. 生成Token
document.getElementById('custom-payment-form').addEventListener('submit', async (e) => {
e.preventDefault();
try {
const result = await apiClientPayment.generateToken({
checkout_session: "checkout_session_id",
payment_method: {
type: "CARD",
vaulted_token: null,
card: {
save: false,
detail: {
number: document.getElementById('card-number').value,
expiration_month: 12,
expiration_year: 25,
security_code: document.getElementById('cvv').value,
holder_name: document.getElementById('cardholder').value,
type: "CREDIT"
}
}
}
});
// Create payment with token
await createPayment(result.token);
} catch (error) {
console.error('Token generation failed:', error);
}
});4. 处理3DS及重定向
const continueResult = await yuno.continuePayment({ showPaymentStatus: false });
if (continueResult?.action === 'REDIRECT_URL') {
window.location.href = continueResult.redirect.init_url;
}使用拱顶Token
const result = await apiClientPayment.generateToken({
checkout_session: "checkout_session_id",
payment_method: {
type: "CARD",
vaulted_token: "saved_token_id",
card: {
detail: {
security_code: "123"
}
}
}
});安全字段(自定义卡片表单)
使用安全的iframe字段构建自定义卡片表单,同时保持PCI合规性。当您需要自定义卡片表单设计、特定字段布局或基于iframe的卡片安全保护时,此方案最为理想。
实施
1. 安装与Initialize
const yuno = await Yuno.initialize('你的公钥');2. 创建安全字段
<div id="card-number-field"></div>
<div id="cvv-field"></div>
<div id="expiry-field"></div>yuno.secureFields({
checkoutSession: 'session_id',
countryCode: 'US',
fields: {
cardNumber: {
elementSelector: '#card-number-field',
placeholder: '1234 5678 9012 3456'
},
cvv: {
elementSelector: '#cvv-field',
placeholder: 'CVV'
},
expiry: {
elementSelector: '#expiry-field',
placeholder: 'MM/YY'
}
},
onFieldChange: (field, isValid) => {
console.log(`${field} valid:`, isValid);
},
async onSubmit(token) {
await createPayment(token);
}
});3. 自定义样式
fields: {
cardNumber: {
elementSelector: '#card-number-field',
style: {
base: {
color: '#333',
fontSize: '16px',
fontFamily: 'Arial, sans-serif'
},
invalid: {
color: '#ff0000'
}
}
}
}多种货币
处理多币种支付,支持自动转换。
// Create session with alternative amount
const session = await fetch('/api/checkout/session', {
method: 'POST',
body: JSON.stringify({
amount: { currency: 'USD', value: 1000 },
alternative_amount: { currency: 'BRL', value: 5000 }, // Display price
country: 'BR'
})
}).then(r => r.json());
// SDK automatically displays both currencies
yuno.startCheckout({
checkoutSession: session.id,
countryCode: 'BR',
// ...
});样式与主题
自定义CSS
yuno.startCheckout({
// ... other config
cssCustomization: {
primaryColor: '#007bff',
errorColor: '#dc3545',
fontFamily: 'Inter, sans-serif'
}
});自定义按钮文字
yuno.startCheckout({
// ... other config
texts: {
pay: 'Complete Purchase',
processing: 'Processing...',
error: 'Payment Failed'
}
});渲染模式
模态显示
yuno.startCheckout({
renderMode: 'modal',
elementSelector: '#payment-container'
});内联显示
yuno.startCheckout({
renderMode: 'element',
elementSelector: '#payment-container'
});预防欺诈
设备指纹识别
由SDK自动收集,用于已配置的欺诈检测服务商(如ClearSale等)。
定制欺诈数据
yuno.startCheckout({
// ... other config
async yunoCreatePayment(token, tokenWithInformation) {
// tokenWithInformation includes fraud data
await fetch('/api/payment/create', {
method: 'POST',
body: JSON.stringify({
token,
device_fingerprint: tokenWithInformation.device_fingerprint,
customer_browser_info: tokenWithInformation.customer.browser_info
})
});
}
});分期付款
启用分期付款
yuno.startCheckout({
// ... other config
card: {
installments: {
enabled: true,
defaultValue: 1
}
}
});定制分期付款计划
在Yuno仪表盘中按支付方式进行配置。
装载机控制
隐藏由乃加载器
yuno.startCheckout({
showLoading: false, // Use your own loader
onLoading: (isLoading) => {
document.getElementById('custom-loader').style.display =
isLoading ? 'block' : 'none';
}
});自定义加载器
yuno.startCheckout({
// ... other config
onLoading: (isLoading) => {
if (isLoading) {
showCustomSpinner();
} else {
hideCustomSpinner();
}
}
});卡片表格类型
扩展表单(独立字段)
yuno.startCheckout({
card: {
type: 'extends' // Shows separate fields for all card details
}
});紧凑表单(单字段)
yuno.startCheckout({
card: {
type: 'only' // Shows single combined field
}
});发行人选择
启用/禁用发行者表单
yuno.startCheckout({
issuersFormEnable: true // Show issuer selection for bank transfers
});付款状态页面
自定义状态处理
yuno.startCheckout({
showPaymentStatus: false, // Handle status yourself
yunoPaymentResult: (data) => {
// Redirect to custom status page
window.location.href = `/payment-status?id=${data.payment_id}&status=${data.status}`;
}
});事件回调
所有可用回调
yuno.startCheckout({
// ... other config
// Payment method selected
yunoPaymentMethodSelected: (data) => {
console.log('Selected:', data.type);
analytics.track('payment_method_selected', { type: data.type });
},
// Payment created (before processing)
async yunoCreatePayment(token, tokenInfo) {
console.log('Creating payment with token:', token);
await processPayment(token);
yuno.continuePayment();
},
// Payment completed
yunoPaymentResult: (data) => {
console.log('Payment result:', data.status);
if (data.status === 'SUCCEEDED') {
gtag('event', 'purchase', { value: data.amount });
}
},
// Error occurred
yunoError: (error, data) => {
console.error('Error:', error, data);
Sentry.captureException(error);
},
// Loading state changed
onLoading: (isLoading) => {
console.log('Loading:', isLoading);
},
// Card form changed
card: {
onChange: ({ error, data }) => {
if (error) {
console.log('Card validation error:', error);
} else {
console.log('Card data:', data);
}
}
}
});浏览器兼容性
SDK支持:
- Chrome 90+
- Firefox 88及以上版本
- Safari 14及以上版本
- 边缘 90+
旧版浏览器的兼容性补丁
<script src="https://polyfill.io/v3/polyfill.min.js"></script>
<script src="https://sdk-web.y.uno/v1.5/main.js"></script>性能优化
懒加载 SDK
// Load SDK only when needed
async function loadYunoSDK() {
if (typeof Yuno !== 'undefined') return;
return new Promise((resolve) => {
const script = document.createElement('script');
script.src = 'https://sdk-web.y.uno/v1.5/main.js';
script.onload = resolve;
document.head.appendChild(script);
});
}
// Use when payment page loads
document.getElementById('checkout-btn').addEventListener('click', async () => {
await loadYunoSDK();
initPayment();
});预连接至Yuno服务器
<link rel="preconnect" href="https://api.y.uno">
<link rel="preconnect" href="https://sdk-web.y.uno">沙盒测试
测试模式配置
// Use test keys (pk_test_*)
const yuno = await Yuno.initialize('pk_test_your_key_here');模拟支付场景
// Backend: Create session with test data
{
amount: { currency: 'USD', value: 1000 },
metadata: {
test_scenario: 'success' // 'success', 'decline', '3ds_required'
}
}错误处理
常见错误代码
yunoError: (error, data) => {
switch(error.code) {
case 'SESSION_EXPIRED':
// Recreate session
refreshSession();
break;
case 'INVALID_CARD':
showError('Please check your card details');
break;
case 'INSUFFICIENT_FUNDS':
showError('Insufficient funds');
break;
case 'NETWORK_ERROR':
showError('Connection error. Please try again.');
break;
default:
showError('An error occurred. Please try again.');
}
}Webhooks集成
通过webhooks在后端验证支付状态:
// Backend webhook handler
app.post('/webhooks/yuno', (req, res) => {
const event = req.body;
switch(event.type) {
case 'payment.succeeded':
fulfillOrder(event.data.payment_id);
break;
case 'payment.failed':
cancelOrder(event.data.payment_id);
break;
}
res.sendStatus(200);
});环境配置
发展
const yuno = await Yuno.initialize('pk_test_dev_key', {
environment: 'sandbox',
debug: true // Enable console logs
});生产
const yuno = await Yuno.initialize('pk_live_prod_key', {
environment: 'production',
debug: false
});1 天前已更新