Business-Bitcoin
view release on metacpan or search on metacpan
lib/Business/Bitcoin/Request.pm view on Meta::CPAN
# -*-cperl-*-
#
# Business::Bitcoin::Request - Bitcoin payment request
# Copyright (c) Ashish Gulhati <biz-btc at hash dot neomailbox.ch>
#
# $Id: lib/Business/Bitcoin/Request.pm v1.051 Tue Oct 16 22:26:58 PDT 2018 $
use warnings;
use strict;
package Business::Bitcoin::Request;
use DBI;
use LWP::UserAgent;
use HTTP::Request;
use Math::EllipticCurve::Prime;
use Math::EllipticCurve::Prime::Point;
use Digest::SHA qw(sha256 sha256_hex hmac_sha512_hex);
use Encode::Base58::BigInt;
use Crypt::RIPEMD160;
use vars qw( $VERSION $AUTOLOAD );
our ( $VERSION ) = '$Revision: 1.051 $' =~ /\s+([\d\.]+)/;
sub new {
my ($class, %args) = @_;
return undef if $args{Amount} !~ /^\d+$/; return undef if $args{StartIndex} and $args{StartIndex} =~ /\D/;
my $db = $args{_BizBTC}->db; my $xpub = $args{_BizBTC}->xpub;
my $timestamp = time;
my $index = defined $args{StartIndex} ? $args{StartIndex} : 'NULL';
my $refid = defined $args{Reference} ? "'$args{Reference}'" : 'NULL';
return undef unless $db->do("INSERT INTO requests values ($index, '$args{Amount}', NULL, $refid, '$timestamp', NULL, NULL);");
$index = $db->last_insert_id('%', '%', 'requests', 'reqid');
$ENV{PATH} = undef;
return undef unless my $address = _getaddress($args{_BizBTC}, $index);
my $rows = $db->do("UPDATE requests set address='$address' where reqid='$index';");
bless { Address => $address,
ID => $index,
Amount => $args{Amount},
DB => $db,
Reference => $args{Reference},
Confirmations => defined $args{Confirmations} ? $args{Confirmations} : 5,
Created => $timestamp }, $class;
}
sub verify {
my $self = shift;
my $ua = new LWP::UserAgent;
my $req = HTTP::Request->new(GET => 'https://blockchain.info/q/addressbalance/' . $self->address . '?confirmations=' . $self->confirmations);
my $res = $ua->request($req);
my $paid = $res->content;
$self->error($paid), return if $paid =~ /\D/;
$self->error('');
$paid >= $self->amount ? $paid : 0;
}
sub _find {
my ($class, %args) = @_;
return unless defined $args{Address} or defined $args{Reference};
return if defined $args{Address} and defined $args{Reference};
return unless defined $args{_BizBTC} and $args{_BizBTC}->db->ping;
my $query = 'SELECT reqid,address,amount,reference,created,processed,status from requests WHERE ' .
(defined $args{Address} ? "address='$args{Address}';" : "reference='$args{Reference}';");
my ($reqid, $address, $amount, $refid, $created, $processed, $status) = $args{_BizBTC}->db->selectrow_array($query);
bless { Address => $address,
Amount => $amount,
Reference => $refid,
ID => $reqid,
DB => $args{_BizBTC}->db,,
Confirmations => defined $args{Confirmations} ? $args{Confirmations} : 5,
Created => $created,
Processed => $processed,
Status => $status
}, $class;
}
sub commit {
my $self = shift;
my $processed = $self->processed;
my $status = $self->status;
my $amount = $self->amount;
my $refid = $self->reference;
my $address = $self->address;
my @updates;
push @updates, "processed = '" . $processed . "'" if $processed;
push @updates, "reference = '" . $refid . "'" if $refid;
push @updates, "status = '" . $status . "'" if $status;
push @updates, "amount = '" . $amount . "'" if $amount;
return 1 unless my $updates = join ',',@updates;
return undef unless $self->db->do("UPDATE requests SET $updates where address='$address';");
return 1;
}
sub _getaddress {
my ($bizbtc, $index) = @_;
my $xpub = $bizbtc->xpub;
my $curve = Math::EllipticCurve::Prime->from_name('secp256k1');
my $xpubdata = Math::BigInt->new(_decode58($xpub))->as_hex;
$xpubdata =~ /.(.{8})(..)(.{8})(.{8})(.{64})(.{66})(.*)/;
my ($ver, $depth, $fp, $i, $c, $Kc) = ($1, $2, $3, $4, $5, $6);
my $K = Math::EllipticCurve::Prime::Point->from_hex(_decompress($Kc));
if ($bizbtc->path eq 'electrum') {
# m/0
my ($Ki, $ci) = _CKDpub($K, $c, 0);
# m/0/$index
my ($Ki2, $ci2) = _CKDpub($Ki, $ci, $index);
return _address(_compress($Ki2));
}
( run in 0.524 second using v1.01-cache-2.11-cpan-39bf76dae61 )