React Native SDK

安装

npm install @yuno-payments/yuno-sdk-react-native

iOS 设置:

cd ios && pod install

安卓系统设置:

无需额外步骤。

📘

要求

React Native 0.Node.js 16+,Android 最低 SDK 21,iOS 14.0+

📘

支持 TypeScript

SDK开箱即用包含TypeScript定义

Initialize

应用程序.tsx:

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

export default function App() {
  useEffect(() => {
    YunoSdk.initialize({
      apiKey: 'your-public-api-key',
      countryCode: 'US',
    });
  }, []);
  
  return <NavigationContainer>{/* your app */}</NavigationContainer>;
}

基本支付流程

import React, { useState, useEffect } from 'react';
import { View, Button, Text, StyleSheet, ScrollView } from 'react-native';
import { YunoSdk, YunoPaymentMethods } from '@yuno-payments/yuno-sdk-react-native';

export default function PaymentScreen() {
  const [checkoutSession, setCheckoutSession] = useState<string | null>(null);
  const [isReady, setIsReady] = useState(false);
  const [paymentMethodSelected, setPaymentMethodSelected] = useState(false);
  
  useEffect(() => {
    initializeCheckout();
    
    // Subscribe to payment events
    const paymentSubscription = YunoSdk.onPaymentStatus((state) => {
      switch (state.status) {
        case 'SUCCEEDED':
          navigateToSuccess();
          break;
        case 'FAILED':
          showError(state.error?.message);
          break;
        case 'PROCESSING':
          console.log('Payment is being processed');
          break;
        default:
          break;
      }
    });
    
    const tokenSubscription = YunoSdk.onOneTimeToken((token) => {
      console.log('OTT received:', token);
      // Send to backend for payment processing
    });
    
    return () => {
      paymentSubscription.remove();
      tokenSubscription.remove();
    };
  }, []);
  
  const initializeCheckout = async () => {
    try {
      // Create checkout session on backend
      const session = await createCheckoutSession();
      setCheckoutSession(session.checkoutSession);
      setIsReady(true);
    } catch (error) {
      console.error('Checkout initialization failed:', error);
    }
  };
  
  const handlePayment = async () => {
    try {
      // Start payment flow
      await YunoSdk.startPayment(true); // true = show payment status screen
    } catch (error) {
      console.error('Payment start failed:', error);
    }
  };
  
  return (
    <ScrollView style={styles.container}>
      <Text style={styles.amount}>$25.00</Text>
      
      {/* Display payment methods */}
      {checkoutSession && (
        <YunoPaymentMethods
          checkoutSession={checkoutSession}
          countryCode="US"
          onPaymentMethodSelected={(selected) => {
            setPaymentMethodSelected(selected);
          }}
        />
      )}
      
      <Button
        title="Pay Now"
        onPress={handlePayment}
        disabled={!isReady || !paymentMethodSelected}
      />
    </ScrollView>
  );
}

async function createCheckoutSession() {
  const response = await fetch('https://api.example.com/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      amount: { currency: 'USD', value: 2500 },
      customer_id: 'cus_123',
      country: 'US',
    }),
  });
  return response.json();
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  amount: {
    fontSize: 32,
    fontWeight: 'bold',
    marginBottom: 24,
  },
});

完整的 TypeScript 示例

import React, { useState, useEffect } from 'react';
import { View, Button, Text, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { YunoSdk, YunoPaymentMethods, YunoPaymentState } from '@yuno-payments/yuno-sdk-react-native';

interface CheckoutSession {
  checkoutSession: string;
  id: string;
}

export default function CheckoutScreen() {
  const [isLoading, setIsLoading] = useState(true);
  const [isProcessing, setIsProcessing] = useState(false);
  const [checkoutSession, setCheckoutSession] = useState<string | null>(null);
  const [paymentMethodSelected, setPaymentMethodSelected] = useState(false);
  
  useEffect(() => {
    loadCheckout();
    
    // Subscribe to payment status
    const paymentSubscription = YunoSdk.onPaymentStatus((state: YunoPaymentState) => {
      setIsProcessing(false);
      
      switch (state.status) {
        case 'SUCCEEDED':
          Alert.alert('Success', 'Payment completed successfully!');
          // Navigate to success screen
          break;
        case 'FAILED':
          Alert.alert('Failed', state.error?.message || 'Payment failed');
          break;
        case 'PROCESSING':
          Alert.alert('Processing', 'Your payment is being processed');
          break;
        default:
          break;
      }
    });
    
    return () => {
      paymentSubscription.remove();
    };
  }, []);
  
  const loadCheckout = async () => {
    try {
      const session = await createCheckoutSession();
      setCheckoutSession(session.checkoutSession);
      setIsLoading(false);
    } catch (error) {
      Alert.alert('Error', 'Failed to load checkout');
      setIsLoading(false);
    }
  };
  
  const processPayment = async () => {
    setIsProcessing(true);
    
    try {
      await YunoSdk.startPayment(true); // Show status screen
    } catch (error) {
      setIsProcessing(false);
      Alert.alert('Error', 'Failed to start payment');
    }
  };
  
  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" />
        <Text style={{ marginTop: 16 }}>Loading checkout...</Text>
      </View>
    );
  }
  
  return (
    <ScrollView style={{ flex: 1, padding: 20 }}>
      <Text style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 20 }}>
        Total: $25.00
      </Text>
      
      {/* Display payment methods */}
      {checkoutSession && (
        <YunoPaymentMethods
          checkoutSession={checkoutSession}
          countryCode="US"
          onPaymentMethodSelected={(selected) => {
            setPaymentMethodSelected(selected);
          }}
          style={{ marginBottom: 20 }}
        />
      )}
      
      <Button
        title={isProcessing ? 'Processing...' : 'Pay Now'}
        onPress={processPayment}
        disabled={isProcessing || !paymentMethodSelected}
      />
    </ScrollView>
  );
}

async function createCheckoutSession(): Promise<CheckoutSession> {
  const response = await fetch('https://api.example.com/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      amount: { currency: 'USD', value: 2500 },
      customer_id: 'cus_123',
      country: 'US',
    }),
  });
  
  if (!response.ok) {
    throw new Error('Failed to create checkout session');
  }
  
  return response.json();
}

处理支付结果

const paymentSubscription = YunoSdk.onPaymentStatus((state) => {
  switch (state.status) {
    case 'SUCCEEDED':
      navigation.navigate('Success');
      break;
    case 'FAILED':
      Alert.alert('Payment Failed', state.error?.message);
      break;
    case 'PROCESSING':
      Alert.alert('Processing', 'Your payment is being processed');
      break;
    case 'REJECTED':
      Alert.alert('Rejected', 'Payment was rejected');
      break;
    default:
      break;
  }
});

// Remember to remove listener when done
// paymentSubscription.remove();

3DS认证

3DS由SDK自动处理。SDK将在需要时呈现3DS挑战。

配置选项

基本参数

参数类型说明
checkoutSession字符串后端会话ID
countryCode字符串ISO国家代码(例如'US')
showPaymentStatus布尔显示支付结果页面

事件监听器

// Payment status
const paymentSubscription = YunoSdk.onPaymentStatus((state) => {
  console.log('Payment status:', state.status);
  console.log('Token:', state.token);
});

// One-time token
const tokenSubscription = YunoSdk.onOneTimeToken((token) => {
  console.log('Token:', token);
  // Send to backend
});

// Enrollment status
const enrollmentSubscription = YunoSdk.onEnrollmentStatus((state) => {
  console.log('Enrollment status:', state.status);
});

// Remove listeners individually (in cleanup)
paymentSubscription.remove();
tokenSubscription.remove();
enrollmentSubscription.remove();

下一步行动

准备探索更多高级功能了吗?查看《高级功能指南》了解:

  • 替代安装方案 - startPaymentLite()startPaymentSeamlessLite() 用于自定义支付方式选择
  • 注册(保存卡片)——保存支付方式以备将来使用
  • 拱顶Token ——一键支付,保存卡片
  • 自定义用户界面(无头集成)——构建完全定制的支付表单
  • 平台特定配置- 处理iOS与Android的差异
  • 样式- 自定义 SDK 外观

另见: