summaryrefslogtreecommitdiff
path: root/FS/FS/msg_template/http.pm
blob: 9c4e68bd7f9b720cd76de3675c00ceb0a0ee7d05 (plain)
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;