高级功能 React Native SDK

React Native的高级配置与自定义集成。

替代安装方案

基本流程采用自动支付方式显示。如需更多控制选项,请使用以下替代方案:

自定义支付方式选择(startPaymentLite)

选择要显示的付款方式:

// 1. Fetch available methods
const methods = await fetchPaymentMethods(sessionId);

// 2. Display in your UI
// 3. Start payment with selected method

await YunoSdk.startPaymentLite(
  {
    checkoutSession: session.checkoutSession,
    methodSelected: {
      paymentMethodType: selectedMethod, // 'CARD', 'PIX', etc.
      vaultedToken: null, // or saved token
    },
    showPaymentStatus: true,
  },
  'US' // Optional country code override
);

简化流程 (startPaymentSeamlessLite)

与精简版类似,但具备自动创建付款功能:

await YunoSdk.startPaymentSeamlessLite({
  checkoutSession: session.checkoutSession,
  paymentMethodType: 'CARD',
  showPaymentStatus: true,
});

注册(保存卡片)

付款时节省

// When creating payment on backend, include vault_on_success flag
async function createPayment(token: string, checkoutSession: string) {
  await fetch('/api/payment/create', {
    method: 'POST',
    body: JSON.stringify({
      one_time_token: token,
      checkout_session: checkoutSession,
      vault_on_success: true, // Save after successful payment
    }),
  });
}

单独注册

// Create customer session on backend
const customerSession = await createCustomerSession('cus_123');

// Set up listener
const enrollmentSubscription = YunoSdk.onEnrollmentStatus((state) => {
  if (state.status === 'SUCCEEDED') {
    console.log('Card saved successfully');
  }
});

// Start enrollment flow
await YunoSdk.enrollmentPayment({
  customerSession: customerSession.id,
  countryCode: 'US',
  showPaymentStatus: true,
});

// Clean up
enrollmentSubscription.remove();

拱顶Token

await YunoSdk.startPaymentLite({
  checkoutSession: session.checkoutSession,
  methodSelected: {
    paymentMethodType: 'CARD',
    vaultedToken: 'vtok_saved_card_123',
  },
  showPaymentStatus: true,
});

自定义用户界面(无头集成)

当您需要完全掌控每个用户界面元素、打造高度定制的结账体验,或拥有开发定制界面的资源时,可构建具备完整用户界面控制权的完全定制化支付表单。

import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';

const CustomPaymentForm = () => {
  const [cardNumber, setCardNumber] = useState('');
  const [expiry, setExpiry] = useState('');
  const [cvv, setCvv] = useState('');
  
  const processPayment = async () => {
    try {
      // 1. Use headless API
      const result = await YunoSdk.generateToken({
        checkoutSession: 'session_id',
        paymentMethod: {
          type: 'CARD',
          card: {
            number: cardNumber,
            expirationMonth: parseInt(expiry.split('/')[0]),
            expirationYear: parseInt(expiry.split('/')[1]),
            securityCode: cvv,
            holderName: 'John Doe',
            type: 'CREDIT',
          },
        },
      }, 'session_id', 'US');
      
      
      // 2. Create payment with token
      await createPayment(result.token);
      
      // 3. Handle 3DS if needed
      if (result.needsChallenge) {
        await YunoSdk.continuePayment('session_id', 'US', true);
      }
      
    } catch (error) {
      console.error('Payment error:', error);
    }
  };
  
  return (
    <View>
      <TextInput
        placeholder="Card Number"
        value={cardNumber}
        onChangeText={setCardNumber}
      />
      <TextInput
        placeholder="MM/YY"
        value={expiry}
        onChangeText={setExpiry}
      />
      <TextInput
        placeholder="CVV"
        value={cvv}
        onChangeText={setCvv}
        secureTextEntry
      />
      <Button title="Pay" onPress={processPayment} />
    </View>
  );
};

造型设计

自定义SDK外观。

// Note: Styling configuration should be done during initialization
YunoSdk.initialize({
  apiKey: 'your-key',
  countryCode: 'US',
  yunoConfig: {
    // Add styling options here
  },
});

错误处理

const handlePayment = async () => {
  useEffect(() => {
    const subscription = YunoSdk.onPaymentStatus((state) => {
      if (state.status === 'FAILED') {
        // Handle payment failure
        Alert.alert('Error', 'Payment failed. Please try again.');
      }
    });
    
    return () => subscription.remove();
  }, []);
  
  try {
    await YunoSdk.startPayment(true);
  } catch (error) {
    console.error('Payment error:', error);
    Alert.alert('Error', error.message);
  }
};

测试与调试

// Use test mode with test API key
YunoSdk.initialize({
  apiKey: 'pk_test_your_key',
  countryCode: 'US',
});

性能

延迟加载

const PaymentScreen = () => {
  const [yunoLoaded, setYunoLoaded] = useState(false);
  
  useEffect(() => {
    // Load Yuno only when needed
    if (!yunoLoaded) {
      YunoSdk.initialize({
        apiKey: 'pk_test_key',
        countryCode: 'US',
      });
      setYunoLoaded(true);
    }
  }, []);
  
  // ...
};

深度链接 / 外部浏览器返回

处理用户在外部支付流程(如3DS认证挑战、银行转账重定向、PIX支付以及重定向至外部浏览器的替代支付方式)后返回应用的情况。

1. 在结账会话中设置回调网址

包含 callback_url 在后端创建结账会话时:

{
  "callback_url": "myapp://return"
}
❗️

重要

没有 callback_url用户可能会被困在外部浏览器中,无法返回您的应用。

2. 配置深度链接

iOS - Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.yourapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
    </dict>
</array>

Android - AndroidManifest.xml:

<activity android:name=".MainActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="myapp"
            android:host="return" />
    </intent-filter>
</activity>

3. 在 React Native 中处理深度链接

import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';
import { Linking } from 'react-native';
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    // Handle initial URL (app opened from closed state)
    Linking.getInitialURL().then((url) => {
      if (url) {
        handleDeepLink(url);
      }
    });
    
    // Handle URL changes (app is running)
    const subscription = Linking.addEventListener('url', (event) => {
      handleDeepLink(event.url);
    });
    
    return () => {
      subscription.remove();
    };
  }, []);
  
  const handleDeepLink = async (url: string) => {
    console.log('Received deep link:', url);
    
    // Check if it's a payment return URL
    if (url.startsWith('myapp://return')) {
      try {
        await YunoSdk.receiveDeeplink(url);
        console.log('Deep link processed successfully');
      } catch (error) {
        console.error('Error processing deep link:', error);
      }
    }
  };
  
  return (
    // Your app
  );
}

4. 退货后继续付款

处理完深度链接后,继续支付流程:

const handleDeepLink = async (url: string) => {
  if (url.startsWith('myapp://return')) {
    try {
      // Process the deep link
      await YunoSdk.receiveDeeplink(url);
      
      // Continue payment flow
      await YunoSdk.continuePayment(
        checkoutSessionId,
        'US',
        true // show payment status
      );
    } catch (error) {
      console.error('Error:', error);
    }
  }
};
💡

最佳实践

  • 始终包含 callback_url 在可能重定向的支付流程中
  • 在iOS和Android设备上测试深度链接处理功能
  • 优雅处理缺失或格式错误的深度链接数据
  • 在从外部浏览器返回后,在您的用户界面中更新付款状态

欺诈预防(ClearSale集成)

通过将ClearSale集成到您的React Native应用中,实现欺诈预防功能。

安卓设置

1. 添加 ClearSale SDK:

添加到 android/app/build.gradle:

dependencies {
    implementation 'br.com.clearsale:cs-android-sdk:4.0.0'
}

2.Initialize :

更新 android/app/src/main/java/.../MainApplication.kt:

import br.com.clearsale.androidsdk.ClearSale

class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        
        // Initialize ClearSale first
        ClearSale.init(this, "your-clearsale-app-key")
        
        // Then initialize React Native
        SoLoader.init(this, false)
    }
}

iOS 设置

1. 添加 ClearSale SDK:

添加到 ios/Podfile:

pod 'ClearSaleSDK'

然后运行:

cd ios && pod install

2.Initialize :

更新 ios/YourApp/AppDelegate.mm:

#import <ClearSale/ClearSale.h>

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Initialize ClearSale
    [ClearSale setupWithApiKey:@"your-clearsale-key"];
    
    // Initialize React Native
    // ...
}

自动集成

一旦ClearSale初始化完成,Yuno SDK将自动:

  • 收集设备fingerprint
  • fingerprint 支付请求发送fingerprint
  • JavaScript 中无需额外代码

测试

验证ClearSale集成:

# Android 日志
adb logcat | grep -i clearsale

# iOS 日志(在 Xcode 控制台)
# 查找 ClearSale 初始化消息

平台特定配置

在 React Native 应用中处理 iOS 与 Android 之间的差异。

条件配置

import { Platform } from 'react-native';
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';

// Initialize with platform-specific config
await YunoSdk.initialize({
  apiKey: 'your-api-key',
  countryCode: 'US',
  yunoConfig: {
    language: 'en',
    cardFlow: Platform.OS === 'ios' ? CardFlow.ONE_STEP : CardFlow.STEP_BY_STEP,
  },
  ...(Platform.OS === 'ios' && {
    iosConfig: {
      // iOS-specific settings
    },
  }),
  ...(Platform.OS === 'android' && {
    androidConfig: {
      // Android-specific settings
    },
  }),
});

平台特有的功能

卡片扫描(仅限安卓系统):

if (Platform.OS === 'android') {
  // Android 系统支持卡片扫描功能
  // 授予相机权限后将自动启用
}

深度链接处理:

const handlePaymentReturn = async (url: string) => {
  if (Platform.OS === 'ios') {
    // iOS-specific handling
    await YunoSdk.receiveDeeplink(url);
  } else if (Platform.OS === 'android') {
    // Android-specific handling
    await YunoSdk.receiveDeeplink(url);
  }
};

最低版本要求

平台最低版本
iOS14.0+
安卓API 21 (5.0)及以上版本
React Native0.70+

平台特定依赖项

原生SDK版本:

平台原生SDK版本
安卓com.yuno.sdk:yuno-sdk-android2.8.1
iOSYunoSDK2.9.0

在两个平台上进行测试

请务必在iOS和Android平台上测试您的集成:

# iOS
npx react-native run-ios

# Android
npx react-native run-android

常见平台差异

特点iOS安卓
卡片扫描❌ 不可用✅ 可用
深度链接通用链接意图过滤器
权限信息.plistAndroidManifest.xml
UI组件原生 iOS 组件Jetpack Compose