1 package FS::part_export::domreg_opensrs;
3 use vars qw(@ISA %info %options $conf);
5 use FS::Record qw(qsearchs qsearch);
7 use FS::part_export::null;
13 FS::part_export::domreg_opensrs - Register or transfer domains with Tucows OpenSRS
17 This module handles registering and transferring domains using a registration service provider (RSP) account
18 at Tucows OpenSRS, an ICANN-approved domain registrar.
20 As a part_export, this module can be designated for use with svc_domain services. When the svc_domain object
21 is inserted into the Freeside database, registration or transferring of the domain may be initiated, depending
22 on the setting of the svc_domain's action field.
26 =item N - Register the domain
28 =item M - Transfer the domain
30 =item I - Ignore the domain for registration purposes
34 This export uses Net::OpenSRS. Registration and transfer attempts will fail unless Net::OpenSRS is installed
35 and LWP::UserAgent is able to make HTTPS posts. You can turn on debugging messages and use the OpenSRS test
36 gateway when setting up this export.
40 @ISA = qw(FS::part_export::null);
42 my @tldlist = qw/com net org biz info name mobi at be ca cc ch cn de dk es eu fr it mx nl tv uk us/;
44 tie %options, 'Tie::IxHash',
45 'username' => { label => 'Reseller user name at OpenSRS',
47 'privatekey' => { label => 'Private key',
49 'password' => { label => 'Password for management account',
51 'masterdomain' => { label => 'Master domain at OpenSRS',
53 'debug_level' => { label => 'Net::OpenSRS debug level',
55 options => [ 0, 1, 2, 3 ],
57 # 'register' => { label => 'Use for registration',
60 # 'transfer' => { label => 'Use for transfer',
63 'tlds' => { label => 'Use this export for these top-level domains (TLDs)',
66 size => scalar(@tldlist),
67 options => [ @tldlist ],
68 default => 'com net org' },
72 'svc' => 'svc_domain',
73 'desc' => 'Domain registration via Tucows OpenSRS',
74 'options' => \%options,
76 Registers and transfers domains via the <a href="http://opensrs.com/">Tucows OpenSRS</a> registrar (using <a href="http://search.cpan.org/dist/Net-OpenSRS">Net::OpenSRS</a>).
77 All of the Net::OpenSRS restrictions apply:
79 <LI>You must have a reseller account with Tucows.
80 <LI>You must add the public IP address of the Freeside server to the 'Script API allow' list in the OpenSRS web interface.
81 <LI>You must generate an API access key in the OpenSRS web interface and enter it below.
82 <LI>All domains are managed using the same user name and password, but you can create sub-accounts for clients.
83 <LI>The user name must be the same as your OpenSRS reseller ID.
84 <LI>You must enter a master domain that all other domains are associated with. That domain must be registered through your OpenSRS account.
86 Some top-level domains offered by OpenSRS have additional business rules not supported by this export. These TLDs cannot be registered or transfered with this export.
87 <BR><BR>Use these buttons for some useful presets:
90 <INPUT TYPE="button" VALUE="OpenSRS Live System (rr-n1-tor.opensrs.net)" onClick='
91 document.dummy.machine.value = "rr-n1-tor.opensrs.net";
92 this.form.machine.value = "rr-n1-tor.opensrs.net";
95 <INPUT TYPE="button" VALUE="OpenSRS Test System (horizon.opensrs.net)" onClick='
96 document.dummy.machine.value = "horizon.opensrs.net";
97 this.form.machine.value = "horizon.opensrs.net";
103 install_callback FS::UID sub {
104 $conf = new FS::Conf;
113 Reformats a phone number according to registry rules. Currently Freeside stores phone numbers
114 in NANPA format and the registry prefers "+CCC.NPANPXNNNN"
121 #if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})( x(\d+))?$/) {
122 if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})$/) {
124 # if $tel .= "$4" if $4;
133 my @invoicing_list = $co->invoicing_list_emailonly;
134 if ( $conf->exists('emailinvoiceautoalways')
135 || $conf->exists('emailinvoiceauto') && ! @invoicing_list
136 || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
137 push @invoicing_list, $co->all_emails;
140 my $email = ($conf->exists('business-onlinepayment-email-override'))
141 ? $conf->config('business-onlinepayment-email-override')
142 : $invoicing_list[0];
145 firstname => $co->first,
146 lastname => $co->last,
147 company => $co->company,
148 address => $co->address1,
150 state => $co->state(),
152 country => uc($co->country()),
154 #phone => format_tel($co->daytime()),
155 phone => $co->daytime() || $co->night,
160 sub validate_contact_info {
164 firstname => "first name",
165 lastname => "last name",
166 address => "street address",
169 zip => "ZIP/postal code",
170 country => "country",
171 email => "email address",
172 phone => "phone number",
175 foreach (keys %fields) {
176 if (!defined($c->{$_}) || !$c->{$_}) {
177 push @err, $fields{$_};
180 if (scalar(@err) > 0) {
181 return "Contact information needs: " . join(', ', @err);
189 return 'live' if $self->machine eq "rr-n1-tor.opensrs.net";
190 return 'test' if $self->machine eq "horizon.opensrs.net";
195 my( $self, $svc_domain ) = ( shift, shift );
197 return if $svc_domain->action eq 'I'; # Ignoring registration, just doing DNS
199 eval "use Net::OpenSRS;";
202 # Get the TLD of the new domain
203 my @bits = split /\./, $svc_domain->domain;
205 return "Can't register subdomains: " . $svc_domain->domain if scalar(@bits) != 2;
209 # See if it's one this export supports
210 my @tlds = split /\s+/, $self->option('tlds');
211 @tlds = map { s/\.//; $_ } @tlds;
212 return "Can't register top-level domain $tld, restricted to: " . $self->option('tlds') if ! grep { $_ eq $tld } @tlds;
214 my $cust_main = $svc_domain->cust_svc->cust_pkg->cust_main;
216 my $c = gen_contact_info($cust_main);
218 my $err = validate_contact_info($c);
221 my $srs = Net::OpenSRS->new();
223 $srs->debug_level( $self->option('debug_level') ); # Output should be in the Apache error log
225 $srs->environment( $self->testmode() );
226 $srs->set_key( $self->option('privatekey') );
228 $srs->set_manage_auth( $self->option('username'), $self->option('password') );
230 my $cookie = $srs->get_cookie( $self->option('masterdomain') );
232 return "Unable to get cookie at OpenSRS: " . $srs->last_response();
235 if ($svc_domain->action eq 'N') {
236 # return "Domain registration not enabled" if !$self->option('register');
237 return $srs->last_response() if !$srs->register_domain( $svc_domain->domain, $c);
238 } elsif ($svc_domain->action eq 'M') {
239 # return "Domain transfer not enabled" if !$self->option('transfer');
240 return $srs->last_response() if !$srs->transfer_domain( $svc_domain->domain, $c);
242 return "Unknown domain action " . $svc_domain->action;
245 return ''; # Should only get here if register or transfer succeeded
249 ## Domain registration exports do nothing on replace. Mainly because we haven't decided what they should do.
250 #sub _export_replace {
251 # my( $self, $new, $old ) = (shift, shift, shift);
257 ## Domain registration exports do nothing on delete. You're just removing the domain from Freeside, not the registry
258 #sub _export_delete {
259 # my( $self, $svc_domain ) = ( shift, shift );
274 L<Net::OpenSRS>, L<FS::part_export_option>, L<FS::export_svc>, L<FS::svc_domain>,
275 L<FS::Record>, schema.html from the base documentation.