File Coverage

blib/lib/Business/Bitcoin.pm
Criterion Covered Total %
statement 47 49 95.9
branch 13 26 50.0
condition 3 7 42.8
subroutine 10 10 100.0
pod 2 2 100.0
total 75 94 79.7


line stmt bran cond sub pod time code
1             # -*-cperl-*-
2             #
3             # Business::Bitcoin - Easy and secure way to accept Bitcoin payments online
4             # Copyright (c) 2016 Ashish Gulhati
5             #
6             # $Id: lib/Business/Bitcoin.pm v1.7 Thu Dec 29 11:03:49 2016 -0500 $
7              
8 2     2   27306 use strict;
  2         4  
  2         74  
9              
10             package Business::Bitcoin;
11              
12 2     2   35 use 5.008001;
  2         5  
13 2     2   7 use warnings;
  2         6  
  2         44  
14 2     2   6 use strict;
  2         8  
  2         27  
15              
16 2     2   2905 use DBI;
  2         25460  
  2         126  
17 2     2   869 use Business::Bitcoin::Request;
  2         4  
  2         65  
18              
19 2     2   11 use vars qw( $VERSION $AUTOLOAD );
  2         1  
  2         899  
20              
21             our ( $VERSION ) = '$Revision: 1.7 $' =~ /\s+([\d\.]+)/;
22              
23             sub new {
24 1     1 1 77312 my $class = shift;
25 1         6 my %args = @_;
26 1 50       5 return undef unless $args{XPUB};
27 1 50 33     6 return undef if $args{StartIndex} and $args{StartIndex} =~ /\D/;
28 1 50       60 unlink $args{DB} if $args{Clobber};
29 1         12 my $db = DBI->connect("dbi:SQLite:dbname=$args{DB}","","");
30 1         9030 my @tables = $db->tables('%','%','requests','TABLE');
31 1 50       1027 unless ($tables[0]) {
32 1 50       5 if ($args{Create}) {
33 1 50       5 return undef unless $db->do('CREATE TABLE requests (
34             reqid INTEGER PRIMARY KEY AUTOINCREMENT,
35             amount int NOT NULL,
36             address text,
37             refid text UNIQUE,
38             created int NOT NULL
39             );');
40 1   50     23447221 my $startindex = $args{StartIndex} || 0;
41 1         2 $startindex--;
42 1 50       11 return unless $db->do("INSERT INTO SQLITE_SEQUENCE values ('requests',$startindex);");
43             }
44             else {
45 0         0 return undef;
46             }
47             }
48 1   50     4311 bless { XPUB => $args{XPUB}, DB => $db, KUCMD => $args{kucmd} || '/usr/local/bin/ku' }, $class;
49             }
50              
51             sub request { # Create a Bitcoin payment request
52 1     1 1 4 my ($self, %args) = @_;
53 1 50       7 return undef if $args{Amount} !~ /^\d+$/;
54              
55             # Workaround for SQLite not starting sequence from 0 when asked to in new()
56 1         9 my $startindex = $self->db->selectcol_arrayref("SELECT seq from SQLITE_SEQUENCE WHERE name='requests';")->[0];
57 1 50       177 my %forcezero; %forcezero = ( StartIndex => 0 ) if $startindex == -1;
  1         5  
58              
59 1         7 my $req = new Business::Bitcoin::Request (%args, _BizBTC => $self, kucmd => $self->kucmd, %forcezero);
60             }
61              
62             sub AUTOLOAD {
63 6     6   5 my $self = shift; (my $auto = $AUTOLOAD) =~ s/.*:://;
  6         19  
64 6 50       13 return if $auto eq 'DESTROY';
65 6 50       20 if ($auto =~ /^(xpub|db|kucmd)$/x) {
66 6 50       9 $self->{"\U$auto"} = shift if (defined $_[0]);
67             }
68 6 50       17 if ($auto =~ /^(xpub|db|version|kucmd)$/x) {
69 6         87 return $self->{"\U$auto"};
70             }
71             else {
72 0           die "Could not AUTOLOAD method $auto.";
73             }
74             }
75              
76             1; # End of Business::Bitcoin
77              
78             =head1 NAME
79              
80             Business::Bitcoin - Easy and secure way to accept Bitcoin payments online
81              
82             =head1 VERSION
83              
84             $Revision: 1.7 $
85             $Date: Thu Dec 29 11:03:49 2016 -0500 $
86              
87             =head1 SYNOPSIS
88              
89             An easy and secure way to accept Bitcoin payments online using an HD
90             wallet, generating new receiving addresses on demand and keeping the
91             wallet private key offline.
92              
93             use Business::Bitcoin;
94              
95             my $bizbtc = new Business::Bitcoin (DB => '/tmp/bizbtc.db',
96             XPUB => 'xpub...',
97             Create => 1);
98              
99             my $request = $bizbtc->request(Amount => 4200);
100              
101             print 'Please pay ' . $request->amount . ' Satoshi ' .
102             'to Bitcoin address ' . $request->address . ".\n" .
103             'Once the payment has ' . $request->confirmations , ' confirmations, ' .
104             "press to continue.\n";
105             readline(*STDIN);
106              
107             print ($request->verify ? "Verified\n" : "Verification failed\n");
108              
109             =head1 HOW TO USE
110              
111             To start receiving Bitcoin payments online, create an HD wallet using
112             any HD wallet app (e.g. Electrum, Bitcoin Armory), get the
113             "Master Public Key" for the wallet (a string beginning with "xpub")
114             and plug it into the constructor's XPUB argument).
115              
116             Now you can receive online payments as outlined above, while keeping
117             your private key secure offline. You should still take all precautions
118             to ensure that your XPUB key on the server is also safe, as its
119             compromise can weaken your security, though it can't in itself lead to
120             the loss of any Bitcoin.
121              
122             =head1 METHODS
123              
124             =head2 new
125              
126             Create a new Business::Bitcoin object and open (or create) the
127             requests database. The following named arguments are required:
128              
129             =over
130              
131             DB - The filename of the requests database
132              
133             XPUB - The master public key for the wallet receiving payments
134              
135             =back
136              
137             The following optional named arguments can be provided:
138              
139             =over
140              
141             Create - Create the requests table if it doesn't exist. If the table
142             doesn't exist and Create is not true, the constructor will return
143             undef. Unset by default.
144              
145             Clobber - Wipe out any existing database file first. Unset by default.
146              
147             StartIndex - Start generating receiving keys from the specified index
148             rather than from 0. Useful if you've already used some receiving
149             addresses before starting to receive payments using this
150             module. Only relevant when Create is true and a new
151             requests table is being created. Ignored when an existing
152             requests table is being used; in that case the index is generated by the
153             database. By default, receiving addresses will be generaed starting
154             from the first one, at index 0.
155              
156             kucmd - The filename of the "ku" command from pycoin. Default is '/usr/local/bin/ku'.
157              
158             =back
159              
160             =head2 request
161              
162             Create a new payment request and generate a new receiving
163             address. Returns a Business::Bitcoin::Request object if successful, or
164             undef on error. The following named argument is required:
165              
166             =over
167              
168             Amount - The amount of the payment requested, in Satoshi.
169              
170             =back
171              
172             The following optional named arguments can be provided:
173              
174             =over
175              
176             Confirmations - The number of confirmations needed to verify payment
177             of this request. The default is 5.
178              
179             Ref - Optional reference ID to be associated with the requst, to
180             facilitate integration with existing ordering systems. If you provide
181             a reference ID it should be unique for each request.
182              
183             =back
184              
185             =head1 ACCESSORS
186              
187             Accessors can be called with no arguments to query the value of an
188             object property, or with a single argument, to set the property to a
189             specific value (unless the property is read only).
190              
191             =head2 db
192              
193             The filename of the requests DB file.
194              
195             =head2 xpub
196              
197             The master public key from which all receiving keys are generated.
198              
199             =head2 kucmd
200              
201             The pathname of the "ku" command from pycoin.
202              
203             =head2 version
204              
205             The version number of this module. Read only.
206              
207             =head1 PREREQUISITES
208              
209             =head2 pycoin
210              
211             The "ku" command from pycoin is used to generate new receiving
212             addresses. You can get pycoin from:
213              
214             https://github.com/richardkiss/pycoin
215              
216             =head2 DBD::SQLite
217              
218             Used to keep track of payment requests.
219              
220             =head2 LWP and an Internet connection
221              
222             Required to verify payments. Currently this is done via the
223             blockchain.info API.
224              
225             =head1 AUTHOR
226              
227             Ashish Gulhati, C<< >>
228              
229             =head1 BUGS
230              
231             Please report any bugs or feature requests to C, or through
232             the web interface at L. I will be notified, and then you'll
233             automatically be notified of progress on your bug as I make changes.
234              
235             =head1 SUPPORT
236              
237             You can find documentation for this module with the perldoc command.
238              
239             perldoc Business::Bitcoin
240              
241             You can also look for information at:
242              
243             =over 4
244              
245             =item * RT: CPAN's request tracker
246              
247             L
248              
249             =item * AnnoCPAN: Annotated CPAN documentation
250              
251             L
252              
253             =item * CPAN Ratings
254              
255             L
256              
257             =item * Search CPAN
258              
259             L
260              
261             =back
262              
263             =head1 LICENSE AND COPYRIGHT
264              
265             Copyright (c) 2016 Ashish Gulhati. All rights reserved.
266              
267             This program is free software; you can redistribute it and/or modify it
268             under the terms of either: the GNU General Public License as published
269             by the Free Software Foundation; or the Artistic License.
270              
271             See http://dev.perl.org/licenses/ for more information.