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