send commission reports by email, #33101
[freeside.git] / FS / FS / msg_template / http.pm
1 package FS::msg_template::http;
2 use base qw( FS::msg_template );
3
4 use strict;
5 use vars qw( $DEBUG $conf );
6
7 # needed to talk to the external service
8 use LWP::UserAgent;
9 use HTTP::Request::Common;
10 use JSON;
11
12 # needed to manage prepared messages
13 use FS::cust_msg;
14
15 our $DEBUG = 1;
16 our $me = '[FS::msg_template::http]';
17
18 sub extension_table { 'msg_template_http' }
19
20 =head1 NAME
21
22 FS::msg_template::http - Send messages via a web service.
23
24 =head1 DESCRIPTION
25
26 FS::msg_template::http is a message processor in which the message is exported
27 to a web service, at both the prepare and send stages.
28
29 =head1 METHODS
30
31 =cut
32
33 sub check {
34   my $self = shift;
35   return 
36        $self->ut_textn('prepare_url')
37     || $self->ut_textn('send_url')
38     || $self->ut_textn('username')
39     || $self->ut_textn('password')
40     || $self->ut_anything('content')
41     || $self->SUPER::check;
42 }
43
44 sub prepare {
45
46   my( $self, %opt ) = @_;
47
48   my $json = JSON->new->canonical(1);
49
50   my $cust_main = $opt{'cust_main'}; # or die 'cust_main required';
51   my $object = $opt{'object'} or die 'object required';
52
53   my $hashref = $self->prepare_substitutions(%opt);
54
55   my $document = $json->decode( $self->content || '{}' );
56   $document = {
57     'msgname' => $self->msgname,
58     'msgtype' => $opt{'msgtype'},
59     %$document,
60     %$hashref
61   };
62   # put override content _somewhere_ so it can be used
63   if ( $opt{'override_content'} ) {
64     $document{'content'} = $opt{'override_content'};
65   }
66
67   my $request_content = $json->encode($document);
68   warn "$me ".$self->prepare_url."\n" if $DEBUG;
69   warn "$request_content\n\n" if $DEBUG > 1;
70   my $ua = LWP::UserAgent->new;
71   my $request = POST(
72     $self->prepare_url,
73     'Content-Type' => 'application/json',
74     'Content' => $request_content,
75   );
76   if ( $self->username ) {
77     $request->authorization_basic( $self->username, $self->password );
78   }
79   my $response = $ua->request($request);
80   warn "$me received:\n" . $response->as_string . "\n\n" if $DEBUG;
81
82   my $cust_msg = FS::cust_msg->new({
83       'custnum'   => $cust_main->custnum,
84       'msgnum'    => $self->msgnum,
85       '_date'     => time,
86       'msgtype'   => ($opt{'msgtype'} || ''),
87   });
88
89   if ( $response->is_success ) {
90     $cust_msg->set(body => $response->decoded_content);
91     $cust_msg->set(status => 'prepared');
92   } else {
93     $cust_msg->set(status => 'failed');
94     $cust_msg->set(error => $response->decoded_content);
95   }
96
97   $cust_msg;
98 }
99
100 =item send_prepared CUST_MSG
101
102 Takes the CUST_MSG object and sends it to its recipient.
103
104 =cut
105
106 sub send_prepared {
107   my $self = shift;
108   my $cust_msg = shift or die "cust_msg required";
109   # don't just fail if called as a class method
110   if (!ref $self) {
111     $self = $cust_msg->msg_template;
112   }
113
114   # use cust_msg->header for anything? we _could_...
115   my $request_content = $cust_msg->body;
116
117   warn "$me ".$self->send_url."\n" if $DEBUG;
118   warn "$request_content\n\n" if $DEBUG > 1;
119   my $ua = LWP::UserAgent->new;
120   my $request = POST(
121     $self->send_url,
122     'Content-Type' => 'application/json',
123     'Content' => $request_content,
124   );
125   if ( $self->username ) {
126     $request->authorization_basic( $self->username, $self->password );
127   }
128   my $response = $ua->request($request);
129   warn "$me received:\n" . $response->as_string . "\n\n" if $DEBUG;
130
131   my $error;
132   if ( $response->is_success ) {
133     $cust_msg->set(status => 'sent');
134   } else {
135     $error = $response->decoded_content;
136     $cust_msg->set(error => $error);
137     $cust_msg->set(status => 'failed');
138   }
139
140   if ( $cust_msg->custmsgnum ) {
141     $cust_msg->replace;
142   } else {
143     $cust_msg->insert;
144   }
145
146   $error;
147 }
148
149 =back
150
151 =head1 BUGS
152
153 =head1 SEE ALSO
154
155 L<FS::Record>, schema.html from the base documentation.
156
157 =cut
158
159 1;