Bulk transfer domains from TransIP

From Openprovider API documentation

Revision as of 10:12, 13 May 2019 by WikiSysop (Talk | contribs)
Jump to: navigation, search

The script and additional documentation can be found in our Knowledge Base

Before using this script, please make sure to read API General Examples

Using this script is at your own risk!

<?php

  $help = "Available parameters:
-f: (required) name of file containing domains to transfer
-d: (optional) how to handle DNS zones; allowed values:
    0: (default) do not create DNS zones in Openprovider; use existing
       nameservers
    1: create DNS zones in Openprovider based on TransIP DNS records;
       put the domain on the Openprovider nameservers after transfer;
       existing zones will not be overwritten
    overwrite: create DNS zones, overwrite any existing zones
-h: (optional) how to handle contacts; allowed values:
    0: (default) the script checks if another TransIP contact with the
       same data was processed before; if so, re-use that contact instead
       of creating a new one
    1: create a new Openprovider handle for every domain contact, even if
       the data is similar to a previously processed contact
-v: (optional) whether or not to show extended information during runtime;
    allowed values:
    0: (default) don't show additional ouput
    1: show additional ouput
-t: (optional) whether to run in test mode or not; allowed values:
    0: run live
    1: (default) run in test mode / read-only; no contacts or zones will
       be created, no domains will be transferred

Examples:
  Run in test mode, full debugging output:
    php transfer-from-transip.php -f domains.txt -v1 -t1

  Run in live mode: transfer domains while create DNS zones (but do not
  overwrite existing ones), show limited output:
    php transfer-from-transip.php -f domains.txt -t0 -d1

Full documentation is available at https://openprovider.zendesk.com/hc/en-us/articles/360019994414
";

  // Openprovider API credentials
  $auth = array('username' => $op_user, 'hash' => $op_hash);

  // TransIP and Openprovider API
  require_once('Transip/DomainService.php');
  require_once('API.php');
  $api = new OP_API ('https://api.openprovider.eu');

  // Read runtime parameters
  $opts = getopt('f:d:t:h:v:', array('help'));
  $domainFile      = $opts['f']; // filename (required)
  $withDns         = $opts['d']; // 0, 1 or overwrite (default = 0)
  $forceNewHandles = $opts['h']; // 0 or 1 (default = 0)
  $verbose         = $opts['v']; // 0 or 1 (default = 0)
  $testMode        = $opts['t']; // 0 or 1 (default = 1)

  if (isset($opts['help'])) {
    echo $help;
    exit;
  }


  // Get list with domains to transfer
  if (file_exists($domainFile)) {
    $domains = file($domainFile, FILE_IGNORE_NEW_LINES);
  }
  else {
    die("Cannot find domain list; file [$f] does not exist\n");
  }

  // Check other parameters
  if (!in_array($withDns, array(0, 1, 'overwrite'))) {
    $withDns = 0;
  }
  if (!in_array($testMode, array(0, 1))) {
    $testMode = 1;
  }
  if (!in_array($forceNewHandles, array(0, 1))) {
    $forceNewHandles = 0;
  }
  if (!in_array($verbose, array(0, 1))) {
    $verbose = 0;
  }

  // Keep track of handles that were already created
  $handleRelations = array();
  if (!$forceNewHandles) {
    if (file_exists('transip-handle-relations.dat')) {
      if ($f = fopen('transip-handle-relations.dat', 'r')) {
        while (!feof($f)) {
          list($md5, $opHandle) = fgetcsv($f);
          $handleRelations[$md5] = $opHandle;
        }
        fclose($f);
      }
      else {
        die("Cannot open file transip-handle-relations.dat\n");
      }
    }
    $fHandles = fopen('transip-handle-relations.dat', 'a');
  }

  foreach ($domains as $dom) {
    $continue = true;

    if ($verbose) {
      echo "Starting domain $dom\n";
      echo "Retrieve data for domain $dom from TransIP API\n";
    }
    try {
      $domain = Transip_DomainService::getInfo($dom);
      if ($verbose) {
        echo "TransIP returned the following data for domain $dom:\n";
        print_r($domain);
      }
    }
    catch(SoapFault $e) {
      // It is possible that an error occurs when connecting to the TransIP Soap API,
      // those errors will be thrown as a SoapFault exception.
      echo "@@ERROR: An error occurred while querying the TransIP API for domain [$dom]: ".htmlspecialchars($e->getMessage())."\n";
      continue;
    }

    $args = array();
    
    // Nameservers
    if ($verbose) {
      echo "Preparing nameservers for domain [$dom]\n";
    }
    if ($withDns) {
      if (!$domain->dnsEntries) {
        echo "@@ERROR: no DNS entries found for import in Openprovider for $dom; skipping this domain\n";
        continue;
      }
      if (createOpenproviderZone($dom, $domain->dnsEntries)) {
        $args['nsGroup'] = 'dns-openprovider';
      }
      else {
        echo "@@ERROR: while creating DNS zone for $dom; skipping this domain\n";
        continue;
      }
    }
    else {
      if (isset($domain->nameservers)) {
        foreach ($domain->nameservers as $ns) {
          $args['nameServers'][] = array(
            'name' => $ns->hostname,
            'ip'   => (isset($ns->ipv4) ? $ns->ipv4 : NULL),
            'ip6'  => (isset($ns->ipv6) ? $ns->ipv6 : NULL),
          );
        }
      }
    }

    // Contacts (handles)
    if ($verbose) {
      echo "Preparing contact handles for domain [$dom]\n";
    }
    foreach ($domain->contacts as $contact) {
      $type = ;
      switch ($contact->type) {
        case 'registrant'     : $type = 'owner'; break;
        case 'administrative' : $type = 'admin'; break;
        case 'technical'      : $type = 'tech'; break;
        default               : echo "@@WARNING: invalid contact type ".$contact->type." for domain [$dom]; skipping\n"; break;
      }
      unset($contact->type);

      $hash = md5(implode(, get_object_vars($contact)));
      if (!$forceNewHandles && isset($handleRelations[$hash])) {
        $opHandle = $handleRelations[$hash];
      }
      else {
        if ($opHandle = createOpenproviderContact($contact)) {
          if (!$testMode) {
            fwrite($fHandles, $hash.','.$opHandle."\n");
            $handleRelations[$hash] = $opHandle;
          }
        }
        else {
          echo "@@ERROR while creating Openprovider contact for $type of $dom\n";
          $continue = false;
          continue 2;
        }
      }
      $args[$type.'Handle'] = $opHandle;
    }

    // Authcode
    $args['authCode'] = $domain->authCode;

    // Unlock domain, if required
    if ($verbose) {
      echo "Unlocking domain [$dom] (if applicable)\n";
    }
    if ($domain->isLocked) {
      if ($testMode) {
        echo "TEST MODE: skipping unlocking domain\n";
      }
      else {
        try {
          $isLocked = Transip_DomainService::unsetLock($dom);
        }
        catch(SoapFault $e)
        {
          // It is possible that an error occurs when connecting to the TransIP Soap API,
          // those errors will be thrown as a SoapFault exception.
          echo "@@ERROR: An error occurred while unlocking domain [$dom]: " . htmlspecialchars($e->getMessage())."\n";
        }
      }
    }

    list($d, $e) = explode('.', $dom, 2);
    $args['domain'] = array(
      'name' => $d,
      'extension' => $e,
    );
    $args['period'] = 1;

    if ($verbose) {
      echo "Start transfer for domain [$dom] in Openprovider with the following data array:\n";
      print_r($args);
    }
    if ($testMode) {
      echo "TEST MODE: skip domain transfer for [$dom]\n";
    }
    else {
      $request = new OP_Request;
      $request->setCommand('transferDomainRequest')
        ->setAuth($auth)
        ->setArgs($args);
      $reply = $api->process($request);
      if ($reply->getFaultCode() != 0) {
        echo "@@ERROR on domain transfer [$dom]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."\n";
        if ($verbose) {
          echo "Full data array:\n";
          print_r($args);
        }
      }
      else {
        echo "Transfer for $dom successfully requested\n";
      }
    }
  }

  function createOpenproviderZone($domain, $dnsEntries) {
    global $api, $auth;
    global $testMode, $withDns, $verbose;

    list($d, $e) = explode('.', $domain, 2);

    // Check if a zone already exists
    $request = new OP_Request;
    $request->setCommand('retrieveZoneDnsRequest')
      ->setAuth($auth)
      ->setArgs(array(
        'name' => $domain,
        'withRecords' => false,
        'withHistory' => false
      ));
    $reply = $api->process($request);
    $response = $reply->getValue();
    if ($response) {
      if ($withDns == 'overwrite') {
        if ($testMode) {
          echo "@@WARNING: TEST MODE: Zone for [$domain] already exists, skip removing of existing zone\n";
        }
        else {
          echo "@@WARNING: Zone for [$domain] already exists; removing existing zone\n";

          $request = new OP_Request;
          $request->setCommand('deleteZoneDnsRequest')
            ->setAuth($auth)
            ->setArgs(array(
              'domain' => array(
                'name' => $d,
                'extension' => $e
              ),
            ));
          $reply = $api->process($request);
          $response = $reply->getValue();
        }
      }
      else {
        echo "@@WARNING: Zone for [$domain] already exists; skipping import\n";
      }
    }

    $records = array();
    foreach ($dnsEntries as $record) {
      if (in_array($record->type, array('NS', 'SOA'))) {
        continue;
      }

      if (in_array($record->type, array('MX', 'SRV'))) {
        list($prio, $value) = explode(' ', $record->content, 2);
      }
      else {
        $prio = NULL;
        $value = $record->content;
      }

      $records[] = array(
        'type'  => $record->type,
        'name'  => ($record->name == '@' ?  : $record->name),
        'value' => ($value == '@' ? $domain : $value),
        'prio'  => $prio,
        'ttl'   => ($record->expire < 600 ? 600 : $record->expire),
      );
    }

    if ($testMode) {
      echo "TEST MODE - skip DNS zone creation for $domain\n";
      if ($verbose) {
        echo "Zone contents:\n";
        print_r($records);
      }
      return true;
    }
    else {
      $request = new OP_Request;
      $request->setCommand('createZoneDnsRequest')
        ->setAuth($auth)
        ->setArgs(array(
          'domain' => array(
            'name' => $d,
            'extension' => $e,
          ),
          'type' => 'master',
          'records' => $records,
        ));
      $reply = $api->process($request);
      if ($reply->getFaultCode() != 0) {
        echo "@@ERROR on DNS zone creation for [$domain]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."; full data array:\n";
        print_r($records);
        return false;
      }
      else {
        if ($verbose) {
          echo "DNS zone for $domain successfully created with the following records:\n";
          print_r($records);
        }
        return true;
      }
    }
  }
  
  function createOpenproviderContact($contact) {
    global $api, $auth;
    global $testMode, $verbose;

    // Split telephone number
    // Country code separated?
    $matches = array();
    if (preg_match('/^(\+?\d+)[ \-\.](.*)$/', $contact->phoneNumber, $matches)) {
      $tel1 = (substr($matches[1], 0, 1) == '+' ?  : '+').$matches[1];
      $rest = preg_replace('/[^\d]/', , $matches[2]);
    }
    // Else consider first 2 numbers the country code
    else {
      $tel = preg_replace('/[^\d]/', , $contact->phoneNumber);
      $tel1 = '+'.substr($tel, 0, 2);
      $rest = $matches[2];
    }
    $tel2 = substr($rest, 0, 2);
    $tel3 = substr($rest, 2);

    // Split address number
    $matches = array();
    if (preg_match('/^\d+$/', $contact->number)) {
      $number = $contact->number;
      $suffix = NULL;
    }
    else if (preg_match('/^(\d+)([^\d].*)$/', $contact->number, $matches)) {
      $number = $matches[1];
      $suffix = $matches[2];
    }
    else {
      $number = 1;
      $suffix = $contact->number;
    }

    $args = array(
      'companyName' => $contact->companyName,
      'name' => array(
        'firstName' => $contact->firstName,
        'prefix' => $contact->middleName,
        'lastName' => $contact->lastName,
      ),
      'phone' => array(
        'countryCode' => $tel1,
        'areaCode' => $tel2,
        'subscriberNumber' => $tel3,
      ),
      'address' => array(
         'street' => $contact->street,
         'number' => $number,
         'suffix' => $suffix,
         'zipcode' => $contact->postalCode,
         'city' => $contact->city,
         'country' => strtoupper($contact->country),
      ),
      'email' => $contact->email,
      'additionalData' => ($contact->companyKvk ? array('companyRegistrationNumber' => $contact->companyKvk) : NULL),
    );

    if ($testMode) {
      echo "TEST MODE - skip handle creation\n";
      if ($verbose) {
        echo "Handle details are the following:\n";
        print_r($args);
      }
      return true;
    }
    else {
      $request = new OP_Request;
      $request->setCommand('createCustomerRequest')
        ->setAuth($auth)
        ->setArgs($args);
      $reply = $api->process($request);
      if ($reply->getFaultCode() != 0) {
        echo "@@ERROR on contact creation for [$domain]: ".$reply->getFaultCode().' - '.$reply->getFaultString()."; full data array:\n";
        print_r($args);
        return false;
      }
      else {
        $response = $reply->getValue();
        if ($verbose) {
          echo "Successfully created handle ".$response['handle']."\n";
        }
        return $response['handle'];
      }
    }
  }

?>
Views
Personal tools