+city
+
+county
+
+state
+
+zip
+
+country
+
+On error, returns a hashref with an 'error' key.
+On success, returns a hashref with 'pkgnum' and 'locationnum' keys,
+containing the new values.
+
+=cut
+
+sub change_package_location {
+ my $self = shift;
+ my %opt = @_;
+ return _shared_secret_error() unless _check_shared_secret($opt{'secret'});
+
+ my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} })
+ or return { 'error' => 'Unknown pkgnum' };
+
+ my %changeopt;
+ $changeopt{'pkgnum'} = $pkgnum;
+
+ my $cust_location = FS::cust_location->new({
+ 'custnum' => $cust_pkg->custnum,
+ %location_hash,
+ });
+ $changeopt{'cust_location'} = $cust_location;
+
+ $cust_pkg->API_change(%changeopt);
+}
+
+=item bill_now OPTION => VALUE, ...
+
+Bills a single customer now, in the same fashion as the "Bill now" link in the
+UI.
+
+Returns a hash reference with a single key, 'error'. If there is an error,
+the value contains the error, otherwise it is empty. Takes a list of keys and
+values as parameters with the following keys:
+
+=over 4
+
+=item secret
+
+API Secret (required)
+
+=item custnum
+
+Customer number (required)
+
+=back
+
+=cut
+
+sub bill_now {
+ my( $class, %opt ) = @_;
+ return _shared_secret_error() unless _check_shared_secret($opt{secret});
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $opt{custnum} })
+ or return { 'error' => 'Unknown custnum' };
+
+ my $error = $cust_main->bill_and_collect( 'fatal' => 'return',
+ 'retry' => 1,
+ 'check_freq' =>'1d',
+ );
+
+ return { 'error' => $error,
+ };
+
+}
+
+
+#next.. Advertising sources?
+
+
+##
+# helper subroutines
+##
+
+sub _check_shared_secret {
+ shift eq FS::Conf->new->config('api_shared_secret');
+}
+
+sub _shared_secret_error {
+ return { 'error' => 'Incorrect shared secret' };
+}