X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=fs_selfservice%2FFS-SelfService%2FSelfService.pm;h=af989ed8a420351bdf45b42b5141c92f61cf6f99;hp=e778f79c27fe9f78573fc987cdcf416d7554c9e2;hb=f5481d63043954fa6fa8a34a5820b23408192f8b;hpb=8405bf17ab0cdf9b227caf18a53131fd5935b377 diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index e778f79c2..af989ed8a 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -9,6 +9,7 @@ use FileHandle; #use IO::Handle; use IO::Select; use Storable 2.09 qw(nstore_fd fd_retrieve); +use Time::HiRes; $VERSION = '0.03'; @@ -26,15 +27,35 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'chfn' => 'passwd/passwd', 'chsh' => 'passwd/passwd', 'login_info' => 'MyAccount/login_info', + 'login_banner_image' => 'MyAccount/login_banner_image', 'login' => 'MyAccount/login', 'logout' => 'MyAccount/logout', + 'switch_acct' => 'MyAccount/switch_acct', + 'switch_cust' => 'MyAccount/switch_cust', 'customer_info' => 'MyAccount/customer_info', 'customer_info_short' => 'MyAccount/customer_info_short', + 'customer_recurring' => 'MyAccount/customer_recurring', + + 'contact_passwd' => 'MyAccount/contact/contact_passwd', + 'list_contacts' => 'MyAccount/contact/list_contacts', + 'edit_contact' => 'MyAccount/contact/edit_contact', + 'delete_contact' => 'MyAccount/contact/delete_contact', + 'new_contact' => 'MyAccount/contact/new_contact', + + 'billing_history' => 'MyAccount/billing_history', 'edit_info' => 'MyAccount/edit_info', #add to ss cgi! 'invoice' => 'MyAccount/invoice', 'invoice_pdf' => 'MyAccount/invoice_pdf', + 'legacy_invoice' => 'MyAccount/legacy_invoice', + 'legacy_invoice_pdf' => 'MyAccount/legacy_invoice_pdf', 'invoice_logo' => 'MyAccount/invoice_logo', 'list_invoices' => 'MyAccount/list_invoices', #? + 'list_payments' => 'MyAccount/list_payments', + 'payment_receipt' => 'MyAccount/payment_receipt', + 'list_payby' => 'MyAccount/list_payby', + 'insert_payby' => 'MyAccount/insert_payby', + 'update_payby' => 'MyAccount/update_payby', + 'delete_payby' => 'MyAccount/delete_payby', 'cancel' => 'MyAccount/cancel', #add to ss cgi! 'payment_info' => 'MyAccount/payment_info', 'payment_info_renew_info' => 'MyAccount/payment_info_renew_info', @@ -47,8 +68,21 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'process_prepay' => 'MyAccount/process_prepay', 'realtime_collect' => 'MyAccount/realtime_collect', 'list_pkgs' => 'MyAccount/list_pkgs', #add to ss (added?) + 'pkg_info' => 'MyAccount/pkg_info', 'list_svcs' => 'MyAccount/list_svcs', #add to ss (added?) 'list_svc_usage' => 'MyAccount/list_svc_usage', + 'svc_status_html' => 'MyAccount/svc_status_html', + 'svc_status_hash' => 'MyAccount/svc_status_hash', + 'set_svc_status_hash' => 'MyAccount/set_svc_status_hash', + 'set_svc_status_listadd' => 'MyAccount/set_svc_status_listadd', + 'set_svc_status_listdel' => 'MyAccount/set_svc_status_listdel', + 'set_svc_status_vacationadd'=> 'MyAccount/set_svc_status_vacationadd', + 'set_svc_status_vacationdel'=> 'MyAccount/set_svc_status_vacationdel', + 'acct_forward_info' => 'MyAccount/acct_forward_info', + 'process_acct_forward' => 'MyAccount/process_acct_forward', + 'list_dsl_devices' => 'MyAccount/list_dsl_devices', + 'add_dsl_device' => 'MyAccount/add_dsl_device', + 'delete_dsl_device' => 'MyAccount/delete_dsl_device', 'port_graph' => 'MyAccount/port_graph', 'list_cdr_usage' => 'MyAccount/list_cdr_usage', 'list_support_usage' => 'MyAccount/list_support_usage', @@ -63,9 +97,16 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'part_svc_info' => 'MyAccount/part_svc_info', 'provision_acct' => 'MyAccount/provision_acct', 'provision_phone' => 'MyAccount/provision_phone', + 'provision_pbx' => 'MyAccount/provision_pbx', 'provision_external' => 'MyAccount/provision_external', + 'provision_forward' => 'MyAccount/provision_forward', 'unprovision_svc' => 'MyAccount/unprovision_svc', 'myaccount_passwd' => 'MyAccount/myaccount_passwd', + 'reset_passwd' => 'MyAccount/reset_passwd', + 'check_reset_passwd' => 'MyAccount/check_reset_passwd', + 'process_reset_passwd' => 'MyAccount/process_reset_passwd', + 'validate_passwd' => 'MyAccount/validate_passwd', + 'list_tickets' => 'MyAccount/list_tickets', 'create_ticket' => 'MyAccount/create_ticket', 'get_ticket' => 'MyAccount/get_ticket', 'adjust_ticket_priority' => 'MyAccount/adjust_ticket_priority', @@ -75,7 +116,9 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'access_info' => 'MyAccount/access_info', 'domain_select_hash' => 'Signup/domain_select_hash', # expose? 'new_customer' => 'Signup/new_customer', + 'new_customer_minimal' => 'Signup/new_customer_minimal', 'capture_payment' => 'Signup/capture_payment', + 'new_prospect' => 'Signup/new_prospect', #N/A 'clear_signup_cache' => 'Signup/clear_cache', 'new_agent' => 'Agent/new_agent', 'agent_login' => 'Agent/agent_login', @@ -89,22 +132,21 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'call_time' => 'PrepaidPhone/call_time', 'call_time_nanpa' => 'PrepaidPhone/call_time_nanpa', 'phonenum_balance' => 'PrepaidPhone/phonenum_balance', - #izoom - #'bulk_processrow' => 'Bulk/processrow', - #conflicts w/Agent one# 'check_username' => 'Bulk/check_username', - #sg - 'ping' => 'SGNG/ping', - 'decompify_pkgs' => 'SGNG/decompify_pkgs', - 'previous_payment_info' => 'SGNG/previous_payment_info', - 'previous_payment_info_renew_info' - => 'SGNG/previous_payment_info_renew_info', - 'previous_process_payment' => 'SGNG/previous_process_payment', - 'previous_process_payment_order_pkg' - => 'SGNG/previous_process_payment_order_pkg', - 'previous_process_payment_change_pkg' - => 'SGNG/previous_process_payment_change_pkg', - 'previous_process_payment_order_renew' - => 'SGNG/previous_process_payment_order_renew', + + 'start_thirdparty' => 'MyAccount/start_thirdparty', + 'finish_thirdparty' => 'MyAccount/finish_thirdparty', + + 'list_quotations' => 'MyAccount/quotation/list_quotations', + 'quotation_new' => 'MyAccount/quotation/quotation_new', + 'quotation_delete' => 'MyAccount/quotation/quotation_delete', + 'quotation_info' => 'MyAccount/quotation/quotation_info', + 'quotation_print' => 'MyAccount/quotation/quotation_print', + 'quotation_add_pkg' => 'MyAccount/quotation/quotation_add_pkg', + 'quotation_remove_pkg' => 'MyAccount/quotation/quotation_remove_pkg', + 'quotation_order' => 'MyAccount/quotation/quotation_order', + + 'freesideinc_service' => 'Freeside/freesideinc_service', + ); @EXPORT_OK = ( keys(%autoload), @@ -157,28 +199,57 @@ sub simple_packet { my $packet = shift; warn "sending ". $packet->{_packet}. " to server" if $DEBUG; - socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!"; - connect(SOCK, sockaddr_un($socket)) or die "connect to $socket: $!"; - nstore_fd($packet, \*SOCK) or die "can't send packet: $!"; - SOCK->flush; - #shoudl trap: Magic number checking on storable file failed at blib/lib/Storable.pm (autosplit into blib/lib/auto/Storable/fd_retrieve.al) line 337, at /usr/local/share/perl/5.6.1/FS/SelfService.pm line 71 + # Retry socket operation 5 times per second + # until successful or $max_retry + my $max_retry = 25; + my $sock_timeout = 5; + my $enable_sock_timeout = 0; - #block until there is a message on socket -# my $w = new IO::Select; -# $w->add(\*SOCK); -# my @wait = $w->can_read; + for my $try ( 1..$max_retry ) { + local $@; - warn "reading message from server" - if $DEBUG; + my $return; - my $return = fd_retrieve(\*SOCK) or die "error reading result: $!"; - die $return->{'_error'} if defined $return->{_error} && $return->{_error}; + eval { + local $SIG{ALRM} = sub{die "socket $socket: timeout ${sock_timeout}s"}; + alarm $sock_timeout + if $enable_sock_timeout; - warn "returning message to client" - if $DEBUG; + socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!"; + connect(SOCK, sockaddr_un($socket)) or die "connect to $socket: $!"; + nstore_fd($packet, \*SOCK) or die "can't send packet: $!"; + SOCK->flush; - $return; + # shoudl trap: Magic number checking on storable file failed at blib/lib/Storable.pm (autosplit into blib/lib/auto/Storable/fd_retrieve.al) line 337, at /usr/local/share/perl/5.6.1/FS/SelfService.pm line 71 + # block until there is a message on socket + # my $w = new IO::Select; + # $w->add(\*SOCK); + # my @wait = $w->can_read; + + warn "reading message from server" + if $DEBUG; + + $return = fd_retrieve(\*SOCK) or die "error reading result: $!"; + die $return->{'_error'} if defined $return->{_error} && $return->{_error}; + + warn "returning message to client" + if $DEBUG; + + return $return; + }; + + return $return + unless $@; + + die "(Attempt $try) $@" + if $try == $max_retry; + + warn "(Attempt $try) $@" + if $DEBUG; + + Time::HiRes::sleep(0.2); + } } =head1 NAME @@ -193,34 +264,107 @@ FS::SelfService - Freeside self-service API # "my account" functionality use FS::SelfService qw( login customer_info invoice cancel payment_info process_payment ); + #new-style login with an email address and password + # can also be used for svc_acct login, set $emailaddress to username@domain + my $rv = login ( { 'email' => $emailaddress, + 'password' => $password, + }, + ); + if ( $rv->{'error'} ) { + #handle login error... + } else { + #successful login + $session_id = $rv->{'session_id'}; + } + + #classic svc_acct-based login with separate username and password my $rv = login( { 'username' => $username, 'domain' => $domain, 'password' => $password, } ); + if ( $rv->{'error'} ) { + #handle login error... + } else { + #successful login + $session_id = $rv->{'session_id'}; + } + #svc_phone login with phone number and PIN + my $rv = login( { 'username' => $phone_number, + 'domain' => 'svc_phone', + 'password' => $pin, + } + ); if ( $rv->{'error'} ) { #handle login error... } else { #successful login - my $session_id = $rv->{'session_id'}; + $session_id = $rv->{'session_id'}; } my $customer_info = customer_info( { 'session_id' => $session_id } ); - #payment_info and process_payment are available in 1.5+ only my $payment_info = payment_info( { 'session_id' => $session_id } ); #!!! process_payment example #!!! list_pkgs example - #!!! order_pkg example + #ordering a package with an svc_acct service + my $rv = order_pkg( { 'session_id' => $session_id, + 'pkgpart' => $pkgpart, + 'svcpart' => $svcpart, + 'username' => $username, + 'domsvc' => $domsvc, #svcnum of svc_domain + '_password' => $password, + } + ); + + #!!! ordering a package with an svc_domain service example + + #!!! ordering a package with an svc_phone service example + + #!!! ordering a package with an svc_external service example + + #!!! ordering a package with an svc_pbx service + + #ordering a package with no service + my $rv = order_pkg( { 'session_id' => $session_id, + 'pkgpart' => $pkgpart, + 'svcpart' => 'none', + } + ); + + #quoting a package, then ordering after confirmation + + my $rv = quotation_new({ 'session_id' => $session_id }); + my $qnum = $rv->{quotationnum}; + # add packages to the quotation + $rv = quotation_add_pkg({ 'session_id' => $session_id, + 'quotationnum' => $qnum, + 'pkgpart' => $pkgpart, + 'quantity' => $quantity, # defaults to 1 + }); + # repeat until all packages are added + # view the pricing information + $rv = quotation_info({ 'session_id' => $session_id, + 'quotationnum' => $qnum, + }); + print "Total setup charges: ".$rv->{total_setup}."\n". + "Total recurring charges: ".$rv->{total_recur}."\n"; + # quotation_info also provides a detailed breakdown of charges, in + # $rv->{sections}. + + # ask customer for confirmation, then: + $rv = quotation_order({ 'session_id' => $session_id, + 'quotationnum' => $qnum, + }); #!!! cancel_pkg example # signup functionality - use FS::SelfService qw( signup_info new_customer ); + use FS::SelfService qw( signup_info new_customer new_customer_minimal ); my $signup_info = signup_info; @@ -283,6 +427,37 @@ see XXXX instead. =item passwd +Changes the password for an existing user in svc_acct. Takes a hash +reference with the following keys: + +=over 4 + +=item username + +Username of the account (required) + +=item domain + +Domain of the account (required) + +=item old_password + +Old password (required) + +=item new_password + +New password (required) + +=item new_gecos + +New gecos + +=item new_shell + +New Shell + +=back + =item chfn =item chsh @@ -300,6 +475,11 @@ following keys: =over 4 +=item email + +Email address (username@domain), instead of username and domain. Required for +contact-based self-service login, can also be used for svc_acct-based login. + =item username Username @@ -361,6 +541,31 @@ first last company address1 address2 city county state zip country daytime night =back +=item customer_recurring HASHREF + +Takes a hash reference as parameter with a single key B +or keys B and B. + +Returns a hash reference with the keys error, custnum and display_recurring. + +display_recurring is an arrayref of hashrefs with the following keys: + +=over 4 + +=item freq + +frequency of charge, in months unless units are specified + +=item freq_pretty + +frequency of charge, suitable for display + +=item amount + +amount charged at this frequency + +=back + =item edit_info HASHREF Takes a hash reference as parameter with any of the following keys: @@ -399,7 +604,7 @@ Invoice text =item list_invoices HASHREF -Returns a list of all customer invoices. Takes a hash references with a single +Returns a list of all customer invoices. Takes a hash reference with a single key, session_id. Returns a hash reference with the following keys: @@ -428,6 +633,197 @@ Invoice date, in UNIX epoch time =back +=item list_payments HASHREF + +Returns a list of all customer payments. Takes a hash reference with a single +key, session_id. + +Returns a hash reference with the following keys: + +=over 4 + +=item error + +Empty on success, or an error message on errors + +=item payments + +Reference to array of hash references with the following keys: + +=over 4 + +=item paynum + +Payment # + +=item _date + +Payument date, in UNIX epoch time + +=item date + +Payment date, in a human-readable format + +=item date_short + +Payment date, in a shorter human-readable format + +=item paid + +Amount paid + +=item payby + +Payment method: CARD, CHEK (electronic check), or BILL (physical check). + +=item paycardtype + +Payment card type + +=item paymask + +Payment card mask + +=item processor + +Processor for cards and electronic checks + +=item auth + +Authorization number + +=item order_number + +Order number + +=back + +=back + +=item list_payby HASHREF + +Returns a list of all stored customer payment information (credit cards and +electronic check accounts). Takes a hash reference with a single key, +session_id. + +Returns a hash reference with the following keys: + +=over 4 + +=item error + +Empty on success, or an error message on errors + +=item payby + +Reference to array of hash references with the following keys: + +=over 4 + +=item custpaybynum + +=item weight + +Numeric weighting. Stored payment information with a lower weight is attempted +first. + +=item payby + +CARD (Automatic credit card), CHEK (Automatic electronic check), DCRD +(on-demand credit card) or DCHK (on-demand electronic check). + +=item paymask + +Masked credit card number (or, masked account and routing numbers) + +=item paydate + +Credit card expiration date + +=item payname + +Exact name on card (or bank name, for electronic checks) + +=item paystate + +For electronic checks, bank state + +=item paytype + +For electronic checks, account type (Personal/Business, Checking/Savings) + +=back + +=back + +=item insert_payby HASHREF + +Adds new stored payment information for this customer. Takes a hash reference +with the following keys: + +=over 4 + +=item session_id + +=item weight + +Numeric weighting. Stored payment information with a lower weight is attempted +first. + +=item payby + +CARD (Automatic credit card), CHEK (Automatic electronic check), DCRD +(on-demand credit card) or DCHK (on-demand electronic check). + +=item payinfo + +Credit card number (or electronic check "account@routing") + +=item paycvv + +CVV2 number / security code + +=item paydate + +Credit card expiration date + +=item payname + +Exact name on card (or bank name, for electronic checks) + +=item paystate + +For electronic checks, bank state + +=item paytype + +For electronic checks, account type (i.e. "Personal Savings", "Personal Checking", "Business Checking")A + +=item payip + +Optional IP address from which payment was submitted + +=back + +If there is an error, returns a hash reference with a single key, B, +otherwise returns a hash reference with a single key, B. + +=item update_payby HASHREF + +Updates stored payment information. Takes a hash reference with the same +keys as insert_payby, as well as B to specify which record +to update. All keys except B and B are optional; +if omitted, the previous values in the record will be preserved. + +If there is an error, returns a hash reference with a single key, B, +otherwise returns a hash reference with a single key, B. + +=item delete_payby HASHREF + +Removes stored payment information. Takes a hash reference with two keys, +B and B. Returns a hash reference with a single key, +B, which is an error message or empty for successful removal. + =item cancel HASHREF Cancels this customer. @@ -441,7 +837,21 @@ success or an error message on errors. Returns information that may be useful in displaying a payment page. -Takes a hash reference as parameter with a single key: B. +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Required session ID + +=item payment_payby + +=item omit_cust_main_county + +Optional, pass a true value to omit cust_main_county data for performance. + +=back Returns a hash reference with the following keys: @@ -720,6 +1130,46 @@ Blank if the service is not over limit, or the date the service exceeded its usa =back +=item pkg_info + +Returns package information for package. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +Package Number + +=back + +Returns a hash reference containing customer package information. The hash reference contains the following keys: + +=over 4 + +=item pkg_label + +Name of this package + +=item pkgpart + +Part package primary key + +=item classnum + +Package class number + +=item error + +error message if errror. + +=back + =item list_svcs Returns service information for this customer. @@ -812,6 +1262,10 @@ Number of total bytes gained by recharge Orders a package for this customer. +If signup_server-realtime is set, bills the new package, attemps to collect +payment and (for auto-payment customers) cancels the package if the payment is +declined. + Takes a hash reference as parameter with the following keys: =over 4 @@ -824,30 +1278,63 @@ Session identifier Package to order (see L). -=item svcpart +=item quantity -Service to order (see L). +Quantity for this package order (default 1). -Normally optional; required only to provision a non-svc_acct service, or if the -package definition does not contain one svc_acct service definition with -quantity 1 (it may contain others with quantity >1). A svcpart of "none" can -also be specified to indicate that no initial service should be provisioned. +=item run_bill_events -=back +If true, runs billing events for the customer after ordering and billing the +package (signup_server-realtime must be set). -Fields used when provisioning an svc_acct service: +=item locationnum -=over 4 +Optional locationnum for this package order, for existing locations. -=item username +Or, for new locations, pass the following fields: address1*, address2, city*, +county, state*, zip*, country. (* = required in this case) -Username +(None of this is required at all if you are just ordering a package +at the customer's existing default service location.) -=item _password +=item address1 -Password +=item address2 -=item sec_phrase +=item city + +=item county + +=item state + +=item zip + +=item country + +=item svcpart + +Service to order (see L). + +Normally optional; required only to provision a non-svc_acct service, or if the +package definition does not contain one svc_acct service definition with +quantity 1 (it may contain others with quantity >1). A svcpart of "none" can +also be specified to indicate that no initial service should be provisioned. + +=back + +Fields used when provisioning an svc_acct service: + +=over 4 + +=item username + +Username + +=item _password + +Password + +=item sec_phrase Optional security phrase @@ -917,149 +1404,588 @@ Returns a hash reference with a single key, B, empty on success, or an error message on errors. The special error '_decline' is returned for declined transactions. -=item change_pkg +=item change_pkg + +Changes a package for this customer. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +Existing customer package. + +=item pkgpart + +New package to order (see L). + +=item quantity + +Quantity for this package order (default 1). + +=back + +Returns a hash reference with the following keys: + +=over 4 + +=item error + +Empty on success, or an error message on errors. + +=item pkgnum + +On success, the new pkgnum + +=back + + +=item renew_info + +Provides useful info for early renewals. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=back + +Returns a hash reference. On errors, it contains a single key, B, with +the error message. Otherwise, contains a single key, B, pointing to +an array refernce of hash references. Each hash reference contains the +following keys: + +=over 4 + +=item bill_date + +(Future) Bill date. Indicates a future date for which billing could be run. +Specified as an integer UNIX timestamp. Pass this value to the B +function. + +=item bill_date_pretty + +(Future) Bill date as a human-readable string. (Convenience for display; +subject to change, so best not to parse for the date.) + +=item amount + +Base amount which will be charged if renewed early as of this date. + +=item renew_date + +Renewal date; i.e. even-futher future date at which the customer will be paid +through if the early renewal is completed with the given B. +Specified as an integer UNIX timestamp. + +=item renew_date_pretty + +Renewal date as a human-readable string. (Convenience for display; +subject to change, so best not to parse for the date.) + +=item pkgnum + +Package that will be renewed. + +=item expire_date + +Expiration date of the package that will be renewed. + +=item expire_date_pretty + +Expiration date of the package that will be renewed, as a human-readable +string. (Convenience for display; subject to change, so best not to parse for +the date.) + +=back + +=item order_renew + +Renews this customer early; i.e. runs billing for this customer in advance. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item date + +Integer date as returned by the B function, indicating the advance +date for which to run billing. + +=back + +Returns a hash reference with a single key, B, empty on success, or an +error message on errors. + +=item cancel_pkg + +Cancels a package for this customer. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgpart + +pkgpart of package to cancel + +=item date + +Optional date, for future cancellation (expiration) instead of immediate +cancellation. Specified as an integer UNIX timestamp ("epoch time"). + +=back + +Returns a hash reference with a single key, B, empty on success, or an +error message on errors. + +=item provision_acct + +Provisions an account (svc_acct). + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +pkgnum of package into which this service is provisioned + +=item svcpart + +svcpart or service definition to provision + +=item username + +=item domsvc + +=item _password + +=back + +=item provision_phone + +Provisions a phone number (svc_phone). + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +pkgnum of package into which this service is provisioned + +=item svcpart + +svcpart or service definition to provision + +=item countrycode + +=item phonenum + +=item address1 + +=item address2 + +=item city + +=item county + +=item state + +=item zip + +=item country + +E911 Address (optional) + +=back + +=item provision_pbx + +Provisions a customer PBX (svc_pbx). + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +pkgnum of package into which this service is provisioned + +=item svcpart + +svcpart or service definition to provision + +=item id + +=item title + +=item max_extensions + +=item max_simultaneous + +=item ip_addr + +=back + +=item provision_external + +Provisions an external service (svc_external). + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +Session identifier + +=item pkgnum + +pkgnum of package into which this service is provisioned + +=item svcpart + +svcpart or service definition to provision + +=item id + +=item title + +=back + +=back + +=head2 "MY ACCOUNT" CONTACT FUNCTIONS + +=over 4 + +=item contact_passwd + +Changes the password for the currently-logged in contact. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +=item new_password + +=back + +Returns a hash reference with a single parameter, B, which contains an +error message, or empty on success. + +=item list_contacts + +Takes a hash reference as parameter with a single key, B. + +Returns a hash reference with two parameters: B, which contains an error +message, or empty on success, and B, a list of contacts. + +B is an array reference of hash references (i.e. an array of structs, + in XML-RPC). Each hash reference (struct) has the following keys: + +=over 4 + +=item contactnum + +=item class + +Contact class name (contact type). + +=item first + +First name + +=item last + +Last name + +=item title + +Position ("Director of Silly Walks"), NOT honorific ("Mr." or "Mrs.") + +=item emailaddress + +Comma-separated list of email addresses + +=item comment + +=item selfservice_access + +Y when enabled + +=back + +=item edit_contact + +Updates information for the currently-logged in contact, or (optionally) the +specified contact. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +=item contactnum + +If already logged in as a contact, this is optional. + +=item first + +=item last + +=item emailaddress + +=back + +Returns a hash reference with a single parameter, B, which contains an +error message, or empty on success. + +=item new_contact + +Creates a new contact. + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +=item first + +=item last + +=item emailaddress + +=item classnum + +Optional contact classnum (TODO: or name) + +=item comment + +=item selfservice_access + +Y to enable self-service access + +=item _password + +=back + +Returns a hash reference with a single parameter, B, which contains an +error message, or empty on success. + +=item delete_contact + +Deletes a contact. (Note: Cannot at this time delete the currently-logged in +contact.) + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item session_id + +=item contactnum + +=back + +Returns a hash reference with a single parameter, B, which contains an +error message, or empty on success. + +=back + +=head2 "MY ACCOUNT" QUOTATION FUNCTIONS + +All of these functions require the user to be logged in, and the 'session_id' +key to be included in the argument hashref.` + +=over 4 + +=item list_quotations HASHREF + +Returns a hashref listing this customer's active self-service quotations. +Contents are: + +=over 4 + +=item quotations + +an arrayref containing an element for each quotation. + +=item quotationnum -Changes a package for this customer. +the primary key -Takes a hash reference as parameter with the following keys: +=item _date -=over 4 +the date it was started -=item session_id +=item num_pkgs -Session identifier +the number of packages -=item pkgnum +=item total_setup -Existing customer package. +the sum of setup fees -=item pkgpart +=item total_recur -New package to order (see L). +the sum of recurring charges =back -Returns a hash reference with the following keys: +=item quotation_new HASHREF -=over 4 +Creates an empty quotation and returns a hashref containing 'quotationnum', +the primary key of the new quotation. -=item error +=item quotation_delete HASHREF -Empty on success, or an error message on errors. +Disables (does not really delete) a quotation. Takes the following arguments: -=item pkgnum +=over 4 -On success, the new pkgnum +=item session_id + +=item quotationnum - the quotation to delete =back +Returns 'error' => a string, which will be empty on success. -=item renew_info +=item quotation_info HASHREF -Provides useful info for early renewals. +Returns total and detailed pricing information on a quotation. -Takes a hash reference as parameter with the following keys: +Takes the following arguments: =over 4 =item session_id -Session identifier +=item quotationnum - the quotation to return =back -Returns a hash reference. On errors, it contains a single key, B, with -the error message. Otherwise, contains a single key, B, pointing to -an array refernce of hash references. Each hash reference contains the -following keys: +Returns a hashref containing: -=over 4 +- total_setup, the total of setup fees (and their taxes) +- total_recur, the total of all recurring charges (and their taxes) +- sections, an arrayref containing an element for each quotation section. + - description, a line of text describing the group of charges + - subtotal, the total of charges in this group (if appropriate) + - detail_items, an arrayref of line items + - pkgnum, the reference number of the package + - description, the package name (or tax name) + - quantity + - amount, the amount charged + If the detail item represents a subtotal, it will instead contain: + - total_item: description of the subtotal + - total_amount: the subtotal amount -=item bill_date -(Future) Bill date. Indicates a future date for which billing could be run. -Specified as a integer UNIX timestamp. Pass this value to the B -function. +=item quotation_print HASHREF -=item bill_date_pretty +Renders the quotation as HTML or PDF. Takes the following arguments: -(Future) Bill date as a human-readable string. (Convenience for display; -subject to change, so best not to parse for the date.) +=over 4 -=item amount +=item session_id -Base amount which will be charged if renewed early as of this date. +=item quotationnum - the quotation to return -=item renew_date +=item format - 'html' or 'pdf' -Renewal date; i.e. even-futher future date at which the customer will be paid -through if the early renewal is completed with the given B. -Specified as a integer UNIX timestamp. +=back -=item renew_date_pretty +Returns a hashref containing 'document', the contents of the file. -Renewal date as a human-readable string. (Convenience for display; -subject to change, so best not to parse for the date.) +=item quotation_add_pkg HASHREF -=item pkgnum +Adds a package to a quotation. Takes the following arguments: -Package that will be renewed. +=over 4 -=item expire_date +=item session_id -Expiration date of the package that will be renewed. +=item pkgpart - the package to add -=item expire_date_pretty +=item quotationnum - the quotation to add it to -Expiration date of the package that will be renewed, as a human-readable -string. (Convenience for display; subject to change, so best not to parse for -the date.) +=item quantity - the package quantity (defaults to 1) + +=item address1, address2, city, state, zip, country - address fields to set +the service location =back -=item order_renew +Returns 'error' => a string, which will be empty on success. -Renews this customer early; i.e. runs billing for this customer in advance. +=item quotation_remove_pkg HASHREF -Takes a hash reference as parameter with the following keys: +Removes a package from a quotation. Takes the following arguments: =over 4 =item session_id -Session identifier - -=item date +=item pkgnum - the primary key (quotationpkgnum) of the package to remove -Integer date as returned by the B function, indicating the advance -date for which to run billing. +=item quotationnum - the quotation to remove it from =back -Returns a hash reference with a single key, B, empty on success, or an -error message on errors. +Returns 'error' => a string, which will be empty on success. -=item cancel_pkg +=item quotation_order HASHREF -Cancels a package for this customer. +Converts the packages in a quotation into real packages. Takes the following +arguments: -Takes a hash reference as parameter with the following keys: +Takes the following arguments: =over 4 =item session_id -Session identifier - -=item pkgpart - -pkgpart of package to cancel +=item quotationnum - the quotation to order =back -Returns a hash reference with a single key, B, empty on success, or an -error message on errors. - =back =head1 SIGNUP FUNCTIONS @@ -1165,6 +2091,147 @@ Default country =back +=item new_customer_minimal HASHREF + +Creates a new customer. + +Current differences from new_customer: An address is not required. promo_code +and reg_code are not supported. If invoicing_list and _password is passed, a +contact will be created with self-service access (no pkgpart or username is +necessary). No initial billing is run (this may change in a future version). + +Takes a hash reference as parameter with the following keys: + +=over 4 + +=item first + +first name (required) + +=item last + +last name (required) + +=item ss + +(not typically collected; mostly used for ACH transactions) + +=item company + +Company name + +=item address1 + +Address line one + +=item address2 + +Address line two + +=item city + +City + +=item county + +County + +=item state + +State + +=item zip + +Zip or postal code + +=item daytime + +Daytime phone number + +=item night + +Evening phone number + +=item fax + +Fax number + +=item payby + +CARD, DCRD, CHEK, DCHK, LECB, BILL, COMP or PREPAY (see L (required) + +=item payinfo + +Card number for CARD/DCRD, account_number@aba_number for CHEK/DCHK, prepaid "pin" for PREPAY, purchase order number for BILL + +=item paycvv + +Credit card CVV2 number (1.5+ or 1.4.2 with CVV schema patch) + +=item paydate + +Expiration date for CARD/DCRD + +=item payname + +Exact name on credit card for CARD/DCRD, bank name for CHEK/DCHK + +=item invoicing_list + +comma-separated list of email addresses for email invoices. The special value 'POST' is used to designate postal invoicing (it may be specified alone or in addition to email addresses), + +=item referral_custnum + +referring customer number + +=item agentnum + +Agent number + +=item pkgpart + +pkgpart of initial package + +=item username + +Username + +=item _password + +Password + +=item sec_phrase + +Security phrase + +=item popnum + +Access number (index, not the literal number) + +=item countrycode + +Country code (to be provisioned as a service) + +=item phonenum + +Phone number (to be provisioned as a service) + +=item pin + +Voicemail PIN + +=back + +Returns a hash reference with the following keys: + +=over 4 + +=item error + +Empty on success, or an error message on errors. The special error '_decline' is returned for declined transactions; other error messages should be suitable for display to the user (and are customizable in under Configuration | View/Edit message catalog) + +=back + =item new_customer HASHREF Creates a new customer. Takes a hash reference as parameter with the @@ -1212,6 +2279,21 @@ State Zip or postal code +=item ship_address1 + +=item ship_address2 + +=item ship_city + +=item ship_county + +=item ship_state + +=item ship_zip + +Optional shipping address fields. If sending an optional shipping address, +ship_address1, ship_city, ship_state and ship_zip are required. + =item daytime Daytime phone number @@ -1358,7 +2440,10 @@ sub regionselector { my $prefix = exists($param->{'prefix'}) ? $param->{'prefix'} : ''; - my $countyflag = 0; + my $disabled = $param->{'disabled'}; + + my $countyflag = $param->{selected_county} ? 1 : 0; + my $cityflag = $param->{selected_city} ? 1 : 0; my %cust_main_county; @@ -1368,17 +2453,17 @@ sub regionselector { foreach my $c ( @{ $param->{'locales'} } ) { #$countyflag=1 if $c->county; $countyflag=1 if $c->{county}; + $cityflag=1 if ($c->{city} && $cityflag); #push @{$cust_main_county{$c->country}{$c->state}}, $c->county; #$cust_main_county{$c->country}{$c->state}{$c->county} = 1; - $cust_main_county{$c->{country}}{$c->{state}}{$c->{county}} = 1; + $cust_main_county{$c->{country}}{$c->{state}}{$c->{county}}{$c->{city}} = 1; } # } - $countyflag=1 if $param->{selected_county}; my $script_html = < - function opt(what,value,text) { - var optionName = new Option(text, value, false, false); + function opt(what,value,text,selected) { + var optionName = new Option(text, value, false, selected); var length = what.length; what.options[length] = optionName; } @@ -1418,8 +2503,37 @@ END #foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) { foreach my $county ( sort keys %{$cust_main_county{$country}{$state}} ) { my $text = $county || '(n/a)'; - $script_html .= - qq!opt(what.form.${prefix}county, "$county", "$text");\n!; + if (!$county) { + if ( $cityflag) { + $script_html .= qq!what.form.${prefix}city.style.display='';\n + what.form.${prefix}city_select.style.display='none';\n! + } + $script_html .= qq!opt(what.form.${prefix}county, "$county", "$text");\n! + #$script_html .= qq!what.form.${prefix}county.style.display='none';\n! + } + else { + $script_html .= qq!var countySelected = false; if ("$param->{selected_county}" == "$text") { countySelected = true; }\n + opt(what.form.${prefix}county, "$county", "$text", countySelected);\n + what.form.${prefix}county.style.display='';\n + county = what.form.${prefix}county.options[what.form.${prefix}county.selectedIndex].text;\n!; + if ( $cityflag) { + $script_html .= qq!\nif ( county == \"$county\" ) {\n!; + foreach my $city ( sort keys %{$cust_main_county{$country}{$state}{$county}} ) { + my $text = $city || '(n/a)'; + if (!$city) { + $script_html .= qq!what.form.${prefix}city.style.display='';\n + what.form.${prefix}city_select.style.display='none';\n! + } + else { + $script_html .= qq!var citySelected = false; if ("$param->{selected_city}" == "$text") { citySelected = true; }\n + opt(what.form.${prefix}city_select, "$city", "$text", citySelected);\n + what.form.${prefix}city.style.display='none';\n + what.form.${prefix}city_select.style.display='';\n! + } + } + $script_html .= "}\n"; + } + } } $script_html .= "}\n"; } @@ -1429,12 +2543,89 @@ END $script_html .= <= 0; i-- ) + what.form.${prefix}city_select.options[i] = null; +END + + foreach my $country ( sort keys %cust_main_county ) { + $script_html .= "\nif ( country == \"$country\" ) {\n"; + foreach my $state ( sort keys %{$cust_main_county{$country}} ) { + $script_html .= "\nif ( state == \"$state\" ) {\n"; + #foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) { + foreach my $county ( sort keys %{$cust_main_county{$country}{$state}} ) { + $script_html .= "\nif ( county == \"$county\" ) {\n"; + foreach my $city ( sort keys %{$cust_main_county{$country}{$state}{$county}} ) { + my $text = $city || '(n/a)'; + if (!$city) { + $script_html .= qq!what.form.${prefix}city.style.display='';\n + what.form.${prefix}city_select.style.display='none';\n! + } + else { + $script_html .= qq!var citySelected = false; if (saved_city == "$text") { citySelected = true; }\n + opt(what.form.${prefix}city_select, "$city", "$text", citySelected);\n + what.form.${prefix}city.style.display='none';\n + what.form.${prefix}city_select.style.display='';\n! + } + } + $script_html .= "}\n"; + } + $script_html .= "}\n"; + } + $script_html .= "}\n"; + } + } + + $script_html .= < END + my $city_html = ''; + if ( $cityflag ) { + if ( scalar (keys %{ $cust_main_county{$param->{'selected_country'}}{$param->{'selected_state'}}{$param->{'selected_county'}} }) > 1 ) { + $city_html .= qq!!; + } else { + $city_html .= qq! + !; + } + } + my $county_html = $script_html; if ( $countyflag ) { - $county_html .= qq!!; foreach my $county ( sort keys %{ $cust_main_county{$param->{'selected_country'}}{$param->{'selected_state'}} } ) { @@ -1458,7 +2649,7 @@ END foreach my $state ( sort keys %{ $cust_main_county{$param->{'selected_country'}} } ) { my $text = $state || '(n/a)'; my $selected = $state eq $param->{'selected_state'} ? 'SELECTED' : ''; - $state_html .= "\n" + $state_html .= "\n" } $state_html .= ''; @@ -1478,7 +2669,7 @@ END my $selected = $country eq $param->{'selected_country'} ? ' SELECTED' : ''; - $country_html .= "\n$country" + $country_html .= "\n" } $country_html .= ''; } else { @@ -1488,7 +2679,7 @@ END } - ($county_html, $state_html, $country_html); + ($county_html, $state_html, $country_html, $city_html); } @@ -1795,8 +2986,9 @@ sub domainselector { '' } - my $text .= qq!Domain!; + $text .= '