summaryrefslogtreecommitdiff
path: root/notes_for_module_writers
blob: cd99cc51681fda0ebfdfea283dfd6c98b921cce8 (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
Notes for module writers
------------------------

Usually talking to your gateway requires that you implement a class performing
the Business::BatchPayment::Processor role. You may also need to implement a
Business::BatchPayment::Transport.

The most common payment batch formats look something like:

HEADER ROW
PAYMENT
PAYMENT
CREDIT (maybe)
PAYMENT
...
TRAILER ROW

where the rows are fixed-length records, possibly separated by newlines.
The return file from the gateway follows a similar format in which each
record identifies one of the transactions as approved or declined.

Business::BatchPayment is designed with this general structure in mind,
but there are many variations and some gateways use completely different
formats.

B:BP::Processor class
---------------------

The Processor class does the work of transforming the B:BP::Batch object
and its associated Item objects into the format used by the gateway, and
vice versa.

"Static" information like the merchant account number or the username and
password for transmitting batches should be declared as attributes of the
Processor class, using the "has" operator.

The external interface to the processor class is only two methods.

- submit( B:BP::Batch ): Prepares and submits a batch of payment requests.

- receive(): Returns any available batches of payment results from the
  gateway.

The base role provides default submit() and receive() methods that should 
work in most cases. The recommended interface is to provide the following
methods:

format_header( B:BP::Batch ): Creates the start of the formatted batch
(usually information such as your merchant account number and the date 
of submission, and sometimes a sum or count of the items). This defaults
to an empty string.

format_item( B:BP::Item, B:BP::Batch ): Takes a single payment request item,
and returns a string representing that item. This will be called for each 
item in the batch, in order. See Business::BatchPayment::Item for the 
attributes of the individual transactions.

format_trailer( B:BP::Batch ): Creates the trailer for the request document.
This also defaults to an empty string.

parse_batch_id( CONTENT ): Given a result document, extracts the batch ID
(as a string) and returns it.

parse_item( LINE ): Given a single line of the result document, returns a
B:BP::Item (see perldoc there for details). This must contain "approved",
and either "tid" or both "customer_id" and "amount".

default_transport: The default method for creating the B:BP::Transport object
for sending the request document to the gateway and retrieving results. If
the gateway uses HTTPS or SFTP in a straightforward way, you may be able
to use one of the existing transport classes (passing the hostname and
login credentials to the constructor). Otherwise, you may need to write 
a transport class. See below.

This is optional; if you don't provide a default transport, then the merchant
system using B:BP just has to provide one of its own. This is the recommended
way to deal with a batch upload that has to be done manually.

default_on_error: The exception handler for format_item or parse_item.
Called with two arguments: the B:BP::Item object or data row, and the 
die() string. This is optional, and can be overridden by the on_format_error
and on_parse_error attributes.


If the gateway's batch format doesn't lend itself to a simple 
header/items/trailer division, you may need to override the higher-level
methods:

format_request( B:BP::Batch ): Converts the entire batch to the format 
expected by the gateway. (By default this simply calls the above methods.)

parse_response( CONTENT ): Converts the entire reply document received from
the gateway to a B:BP::Batch object. As above, each reply item must contain
"approved", and either "tid" or both "customer_id" and "amount".

B:BP::Transport class
---------------------

This must implement two methods, "upload" and "download".

"upload" takes the batch content produced by format_request as an argument,
and does whatever is necessary to send it to the gateway. "download" takes
no arguments, and returns a list of strings containing batch results.

The "SFTP", "HTTPS", and "File" subclasses all have "upload" and "download"
methods which may be suitable, but if not, they also expose access to their
protocols. For example, if the file needs to be compressed before being 
submitted by SFTP, you could create a B:BP::Transport::SFTP subclass which 
provides an "upload" method. That method would compress the file and then
call "$self->put" to send it to the host and path defined in the transport's
attributes.

B:BP::TestMode
--------------

Include this role in your Processor module if it supports a test mode.
It will create a "test_mode" attribute which can be set to true; the processor
or transport should check this attribute, and do whatever is necessary to 
enable test mode (submitting to a different server, setting a flag within
the request itself, etc.).

If the processor doesn't have a test mode (or enables it on a per-account
basis, i.e. test mode is selected by using a test login), then don't include
this role, and attempts to set test_mode will simply fail.