# @montarist/nestpay-api-v2

An unofficial, comprehensive TypeScript API client for Nestpay payment gateway with **FULL support for all 3D Secure models**, **comprehensive provider management**, and mobile app integration.

## 🚀 What's New in v2

- ✅ **Complete 3D Secure Model Support**: Classic, 3D Pay, and 3D Pay Hosting
- ✅ **Comprehensive Provider System**: Support for 30+ Turkish banks
- ✅ **Runtime Provider Switching**: Change banks dynamically
- ✅ **Auto-Detection**: Automatic provider detection from client ID
- ✅ **Custom Endpoints**: Support for custom bank endpoints
- ✅ **Mobile App Optimized**: Perfect for React Native and mobile backends
- ✅ **Advanced Hash Security**: SHA1, SHA256, SHA512 with model-specific algorithms
- ✅ **Enhanced Type Safety**: Full TypeScript interfaces for all models and providers

## 📋 Features

- 🚀 **Full TypeScript Support** with comprehensive interfaces
- 🔒 **All 3D Secure Models**: Classic, 3D Pay (recommended), and 3D Pay Hosting
- 🏦 **Complete Provider Support**: 30+ Turkish banks with auto-detection
- 💳 **Complete Payment Operations**: Direct payments, refunds, voids, queries
- 📱 **Mobile App Ready**: React Native WebView integration examples
- 🛡️ **Enhanced Security**: Model-specific hash verification
- ⚡ **Modern Architecture**: Promise-based with async/await
- 🔄 **Runtime Flexibility**: Switch between models and providers dynamically
- 🌍 **Multi-Language**: Turkish, English, German, French
- 📖 **Comprehensive Examples**: Real-world usage patterns

## 📦 Installation

```bash
npm install @montarist/nestpay-api-v2
```

## 🏦 Supported Banks & Providers

### Major Turkish Banks

- **İş Bankası** - Auto-detected from client ID
- **Yapı Kredi** - Full 3D model support
- **Garanti BBVA** - Enhanced security
- **Akbank** - Modern endpoints
- **Ziraat Bankası** - Government bank
- **Halk Bankası** - Public bank
- **VakıfBank** - Full integration

### International Banks

- **HSBC, ING, Citibank, Deutsche Bank**
- **JPMorgan Chase, Standard Chartered**

### Digital Payment Providers

- **Paykasa** - Payment gateway
- **Param** - Digital wallet
- **Custom** - Your own endpoints

_Total: 30+ providers with automatic endpoint management_

## 🎯 Provider System Overview

### Auto-Detection

```typescript
import { NestpayClient, BankProvider } from "@montarist/nestpay-api-v2";

// Auto-detect from client ID
const provider = NestpayClient.detectProviderFromClientId("64000001"); // Returns: ISBANK
const displayName = NestpayClient.getProviderDisplayName(provider); // Returns: "İş Bankası"
```

### Provider-Specific Configuration

```typescript
import {
  NestpayClient,
  BankProvider,
  StoreType,
  ThreeDModel,
} from "@montarist/nestpay-api-v2";

// İş Bankası configuration
const isbankConfig = {
  clientId: "64000001",
  username: "your_username",
  password: "your_password",
  storeKey: "your_store_key",
  storeType: StoreType.PAY_3D,
  provider: BankProvider.ISBANK, // Explicit provider
  threeDModel: ThreeDModel.PAY,
  isTestMode: true,
};

// Yapı Kredi configuration
const yapikrediConfig = {
  clientId: "67000001",
  // ... other config
  provider: BankProvider.YAPIKREDI,
  hashAlgorithm: HashAlgorithm.SHA1, // Different hash algorithm
};

const isbankClient = new NestpayClient(isbankConfig);
const yapikrediClient = new NestpayClient(yapikrediConfig);
```

### Runtime Provider Switching

```typescript
// Create client with one provider
const client = new NestpayClient(isbankConfig);
console.log(client.getProviderDisplayName()); // "İş Bankası"

// Switch to different provider at runtime
client.setProvider(BankProvider.YAPIKREDI);
console.log(client.getProviderDisplayName()); // "Yapı Kredi"

// Get current endpoints
console.log(client.getCurrentEndpoints());
// { api: "https://setmpos.ykb.com/...", threeD: "https://..." }
```

## 🚀 Quick Start

### Basic Provider Configuration

```typescript
import {
  NestpayClient,
  BankProvider,
  StoreType,
  ThreeDModel,
  Currency,
} from "@montarist/nestpay-api-v2";

// Configuration with auto-detected provider
const config = {
  clientId: "isbank64000001", // Will auto-detect İş Bankası
  username: "your_username",
  password: "your_password",
  storeKey: "your_store_key",
  storeType: StoreType.PAY_3D,
  threeDModel: ThreeDModel.PAY, // Best for mobile apps
  isTestMode: true,
};

const nestpay = new NestpayClient(config);
console.log(`Using: ${nestpay.getProviderDisplayName()}`); // "İş Bankası"
```

### Multi-Provider E-commerce Setup

```typescript
// E-commerce with primary, secondary, and fallback providers
const ecommerceConfig = {
  // ... base config
  provider: BankProvider.ISBANK, // Primary
};

const client = new NestpayClient(ecommerceConfig);

try {
  // Try primary provider (İş Bankası)
  const result = await client.processDirectPayment(paymentRequest);

  if (!result.data?.success) {
    // Switch to secondary provider (Garanti)
    client.setProvider(BankProvider.GARANTI);
    const retryResult = await client.processDirectPayment(paymentRequest);

    if (!retryResult.data?.success) {
      // Final fallback (Akbank)
      client.setProvider(BankProvider.AKBANK);
      return await client.processDirectPayment(paymentRequest);
    }

    return retryResult;
  }

  return result;
} catch (error) {
  console.error("All providers failed:", error);
}
```

## 💳 3D Pay Payment (Recommended for Mobile)

```typescript
// 3D Pay payment - best for mobile apps
const paymentRequest = {
  model: ThreeDModel.PAY,
  amount: 100.5,
  currency: Currency.TRY,
  orderId: "mobile-order-123",
  creditCard: {
    pan: "4508034508034509",
    expiry: "1225",
    cvv: "123",
    cardHolderName: "John Doe",
  },
  callbackUrl: "https://yourapp.com/payment/callback",
  failureUrl: "https://yourapp.com/payment/failure",
  refreshTime: 3, // Auto-submit after 3 seconds for mobile
  customer: {
    email: "customer@example.com",
  },
};

const result = await nestpay.initiate3DPayment(paymentRequest);

if (result.data) {
  console.log("Provider:", nestpay.getProviderDisplayName());
  console.log("3D Model:", result.data.model); // 'PAY'
  console.log("Refresh Time:", result.data.refreshTime); // 3
  console.log("Form Action:", result.data.formAction);

  // Redirect user to result.data.formAction
}
```

## 📱 Mobile App Integration

### NestJS Backend with Provider Support

```typescript
@Controller("payment")
export class PaymentController {
  private clients: Map<BankProvider, NestpayClient> = new Map();

  constructor() {
    // Initialize multiple provider clients
    this.clients.set(BankProvider.ISBANK, new NestpayClient(isbankConfig));
    this.clients.set(
      BankProvider.YAPIKREDI,
      new NestpayClient(yapikrediConfig)
    );
    this.clients.set(BankProvider.GARANTI, new NestpayClient(garantiConfig));
  }

  @Post("3d-pay/initiate")
  async initiate3DPay(@Body() data: any) {
    // User can select their preferred bank
    const selectedProvider = data.provider || BankProvider.ISBANK;
    const client = this.clients.get(selectedProvider);

    const request = {
      model: ThreeDModel.PAY,
      amount: data.amount,
      currency: Currency.TRY,
      orderId: data.orderId,
      creditCard: data.creditCard,
      callbackUrl: `${process.env.BACKEND_URL}/payment/callback`,
      failureUrl: `${process.env.BACKEND_URL}/payment/failure`,
      refreshTime: 3, // Quick for mobile
    };

    const result = await client.initiate3DPayment(request);

    return {
      success: true,
      provider: client.getProviderDisplayName(),
      threeDUrl: result.data?.formAction,
      orderId: data.orderId,
    };
  }

  @Post("callback")
  async handleCallback(@Body() callbackData: any) {
    // Detect provider from callback or use default
    const provider = this.detectProviderFromCallback(callbackData);
    const client = this.clients.get(provider);

    // Verify hash with provider-specific logic
    const isValid = client.verify3DCallbackHash(callbackData, ThreeDModel.PAY);

    if (!isValid) {
      return { success: false, message: "Invalid hash" };
    }

    const result = await client.complete3DPayment(callbackData);

    // Redirect mobile app with provider info
    return `
      <script>
        window.location.href = 'myapp://payment/${
          result.data?.success ? "success" : "failure"
        }?orderId=${callbackData.orderId}&provider=${provider}';
      </script>
    `;
  }
}
```

### React Native Integration

```typescript
// Mobile app with provider selection
import { Picker } from "@react-native-picker/picker";

const PaymentScreen = () => {
  const [selectedProvider, setSelectedProvider] = useState(BankProvider.ISBANK);
  const [threeDUrl, setThreeDUrl] = useState("");

  const providers = [
    { value: BankProvider.ISBANK, label: "İş Bankası" },
    { value: BankProvider.YAPIKREDI, label: "Yapı Kredi" },
    { value: BankProvider.GARANTI, label: "Garanti BBVA" },
    { value: BankProvider.AKBANK, label: "Akbank" },
  ];

  const initiatePayment = async () => {
    const response = await fetch("/payment/3d-pay/initiate", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        provider: selectedProvider,
        amount: 100.5,
        orderId: `mobile-${Date.now()}`,
        creditCard: {
          pan: "4508034508034509",
          expiry: "1225",
          cvv: "123",
          cardHolderName: "Mobile User",
        },
      }),
    });

    const result = await response.json();
    setThreeDUrl(result.threeDUrl);
  };

  return (
    <View>
      <Text>Select Your Bank:</Text>
      <Picker
        selectedValue={selectedProvider}
        onValueChange={setSelectedProvider}
      >
        {providers.map((provider) => (
          <Picker.Item
            key={provider.value}
            label={provider.label}
            value={provider.value}
          />
        ))}
      </Picker>

      <Button title="Pay with 3D Secure" onPress={initiatePayment} />

      {threeDUrl && (
        <ThreeDSecureWebView
          threeDUrl={threeDUrl}
          onSuccess={(data) => console.log("Payment success:", data)}
          onFailure={(error) => console.log("Payment failed:", error)}
        />
      )}
    </View>
  );
};
```

## 🔄 Advanced Provider Features

### Custom Provider Endpoints

```typescript
import { BankProvider, ProviderEndpoints } from "@montarist/nestpay-api-v2";

const customEndpoints: ProviderEndpoints = {
  production: {
    api: "https://my-custom-bank.com/api/payment",
    threeD: "https://my-custom-bank.com/3dsecure",
  },
  test: {
    api: "https://test.my-custom-bank.com/api/payment",
    threeD: "https://test.my-custom-bank.com/3dsecure",
  },
};

const customConfig = {
  // ... other config
  provider: BankProvider.CUSTOM,
  customEndpoints,
};

const customClient = new NestpayClient(customConfig);
```

### Provider Validation

```typescript
import { ProviderEndpointManager } from "@montarist/nestpay-api-v2";

// Validate provider configuration
const validation = ProviderEndpointManager.validateProvider(
  BankProvider.CUSTOM,
  customEndpoints
);

if (!validation.isValid) {
  console.error("Provider validation failed:", validation.errors);
}

// Get all available providers
const allProviders = NestpayClient.getAvailableProviders();
console.log(`Total providers: ${allProviders.length}`);

// Get provider endpoints
const endpoints = ProviderEndpointManager.getEndpoints(
  BankProvider.ISBANK,
  true // test mode
);
```

## 💳 Complete Payment Operations

### Direct Payment with Provider Switching

```typescript
const directPayment = async (
  paymentData: any,
  preferredProvider: BankProvider
) => {
  const client = new NestpayClient({
    // ... config
    provider: preferredProvider,
  });

  try {
    const result = await client.processDirectPayment(paymentData);

    if (!result.data?.success && result.error) {
      // Try fallback provider
      client.setProvider(BankProvider.GARANTI);
      console.log(`Retrying with: ${client.getProviderDisplayName()}`);

      return await client.processDirectPayment(paymentData);
    }

    return result;
  } catch (error) {
    console.error(
      `Payment failed with ${client.getProviderDisplayName()}:`,
      error
    );
    throw error;
  }
};
```

### Provider-Aware Refund Processing

```typescript
const processRefund = async (orderId: string, provider: BankProvider) => {
  const client = new NestpayClient({
    // ... config
    provider,
  });

  console.log(`Processing refund with: ${client.getProviderDisplayName()}`);

  const result = await client.processRefund({
    orderId,
    amount: 50.0,
    currency: Currency.TRY,
  });

  if (result.data?.success) {
    console.log(`✅ Refund successful via ${client.getProviderDisplayName()}`);
    console.log(`Refund amount: ${result.data.refundAmount}`);
  }

  return result;
};
```

## 🔐 Enhanced Security Features

### Provider-Specific Hash Algorithms

```typescript
// Different providers may use different hash algorithms
const configs = {
  isbank: {
    provider: BankProvider.ISBANK,
    hashAlgorithm: HashAlgorithm.SHA256, // İş Bankası prefers SHA256
  },
  yapikredi: {
    provider: BankProvider.YAPIKREDI,
    hashAlgorithm: HashAlgorithm.SHA1, // Yapı Kredi uses SHA1
  },
  garanti: {
    provider: BankProvider.GARANTI,
    hashAlgorithm: HashAlgorithm.SHA512, // Garanti uses SHA512
  },
};
```

### Model & Provider-Specific Hash Verification

```typescript
// Verify hash with specific provider and model
const verifyCallback = (
  callbackData: any,
  provider: BankProvider,
  model: ThreeDModel
) => {
  const client = new NestpayClient({
    // ... config
    provider,
  });

  const isValid = client.verify3DCallbackHash(callbackData, model);

  console.log(
    `Hash verification for ${client.getProviderDisplayName()} + ${model}: ${
      isValid ? "✅" : "❌"
    }`
  );

  return isValid;
};
```

## 🌍 Multi-Language & Multi-Currency

```typescript
import { Language, Currency } from "@montarist/nestpay-api-v2";

const internationalConfig = {
  // ... other config
  language: Language.ENGLISH, // TURKISH, ENGLISH, GERMAN, FRENCH
  provider: BankProvider.HSBC, // International bank
  isTestMode: true,
};

const payment = {
  amount: 150.75,
  currency: Currency.EUR, // TRY, USD, EUR, GBP
  // ... other payment data
};
```

## 🧪 Test Cards and Environment

### Test Card Information

```javascript
// Test cards for all providers and models
Card Number: 4508034508034509
Expiry: 12/25
CVV: 123
3D Secure Password: 123456

// Provider-specific test cards
İş Bankası Test: 4508034508034509
Yapı Kredi Test: 4022774022774026
Garanti Test: 4824894282414023
```

### Environment Variables

```bash
# Nestpay Configuration
NESTPAY_CLIENT_ID=your_client_id
NESTPAY_USERNAME=your_username
NESTPAY_PASSWORD=your_password
NESTPAY_STORE_KEY=your_store_key

# Provider Selection (optional - will auto-detect)
NESTPAY_PROVIDER=isbank

# Backend URL (for mobile apps)
BACKEND_URL=https://your-backend.com
```

## 📊 Provider Performance Monitoring

```typescript
// Monitor provider performance
const monitorProviders = async () => {
  const providers = [
    BankProvider.ISBANK,
    BankProvider.YAPIKREDI,
    BankProvider.GARANTI,
  ];
  const results = [];

  for (const provider of providers) {
    const startTime = Date.now();

    try {
      const client = new NestpayClient({
        // ... config
        provider,
      });

      // Test endpoint connectivity
      const endpoints = client.getCurrentEndpoints();
      const response = await fetch(endpoints.api, { method: "HEAD" });

      results.push({
        provider: client.getProviderDisplayName(),
        status: response.ok ? "healthy" : "degraded",
        responseTime: Date.now() - startTime,
        endpoint: endpoints.api,
      });
    } catch (error) {
      results.push({
        provider: NestpayClient.getProviderDisplayName(provider),
        status: "unhealthy",
        responseTime: -1,
        error: error.message,
      });
    }
  }

  return results;
};
```

## 📖 Complete Examples

Check out the `examples/` directory for comprehensive usage examples:

- `examples/provider-system-usage.ts` - Complete provider system guide
- `examples/three-models-usage.ts` - All 3D models with provider support
- `examples/nestjs-backend-example.ts` - Complete NestJS backend with multi-provider
- `examples/mobile-app-integration.md` - Mobile app integration guide

## 🎯 Best Practices

### Production Configuration

```typescript
// ✅ Recommended production setup
const productionConfig = {
  provider: BankProvider.ISBANK, // Explicit provider
  threeDModel: ThreeDModel.PAY, // Best for mobile
  hashAlgorithm: HashAlgorithm.SHA256, // Enhanced security
  isTestMode: false, // Production mode
  // Custom endpoints as backup
  customEndpoints: backupEndpoints,
};
```

### Error Handling with Providers

```typescript
const robustPayment = async (paymentData: any) => {
  const primaryProviders = [BankProvider.ISBANK, BankProvider.GARANTI];
  const fallbackProviders = [BankProvider.AKBANK, BankProvider.YAPIKREDI];

  // Try primary providers first
  for (const provider of primaryProviders) {
    try {
      const client = new NestpayClient({ ...config, provider });
      const result = await client.processDirectPayment(paymentData);

      if (result.data?.success) {
        console.log(
          `✅ Payment successful with ${client.getProviderDisplayName()}`
        );
        return result;
      }
    } catch (error) {
      console.warn(
        `❌ ${NestpayClient.getProviderDisplayName(provider)} failed:`,
        error
      );
    }
  }

  // Try fallback providers
  for (const provider of fallbackProviders) {
    // ... same logic
  }

  throw new Error("All providers failed");
};
```

## 🤝 Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ⚠️ Disclaimer

This is an unofficial library. Always test thoroughly in a sandbox environment before using in production. The authors are not responsible for any financial losses or damages.

## 🆘 Support

- 📚 [Documentation](https://github.com/montarist/nestpay-api-v2)
- 🐛 [Issue Tracker](https://github.com/montarist/nestpay-api-v2/issues)
- 💬 [Discussions](https://github.com/montarist/nestpay-api-v2/discussions)

---

Made with ❤️ for Turkish developers building amazing payment solutions.

**🎯 Perfect for your mobile app with comprehensive provider support! 🚀**

### Key Benefits:

- ✅ **30+ Bank Support** with automatic endpoint management
- ✅ **Runtime Provider Switching** for high availability
- ✅ **Auto-Detection** from client ID
- ✅ **3D Secure Models** optimized for mobile
- ✅ **Production Ready** with comprehensive error handling
- ✅ **Type Safe** with full TypeScript support
