Revision 690 (by ahitrov, 2018/07/30 10:05:12) Sberbank gate. One-stage JSON API

package payments::Provider::Base;

use strict;
use warnings 'all';
use Contenido::Globals;
use payments::Keeper;


sub new {
    my ($proto, %params) = @_;
    my $class = ref($proto) || $proto;
    my $self = {};
    my $prefix = $class =~ /\:\:(\w+)$/ ? lc($1) : undef;
    return	unless $prefix;

    $self->{payment_system} = $prefix;
    $self->{app_id} =		$state->{payments}->{$prefix."_app_id"};
    $self->{secret} =		$state->{payments}->{$prefix."_app_secret"};
    $self->{currency} =		$state->{payments}->{$prefix."_currency_code"};
    $self->{test_mode} =	$state->{payments}->{$prefix."_test_mode"};

    bless $self, $class;

    return $self;
}


sub id {
    my $self = shift;
    return $self->{app_id};
}

sub app_id {
    my $self = shift;
    return $self->{app_id};
}

sub secret {
    my $self = shift;
    return $self->{secret};
}

sub test_mode {
    my $self = shift;
    return $self->{test_mode};
}

sub currency {
    my $self = shift;
    return $self->{currency};
}

sub currency_code {
    my $self = shift;
    return $self->{currency};
}

sub payment_system {
    my $self = shift;
    return $self->{payment_system};
}

#################################
# Пытается зарегистрировать операцию по order_id.
# В случае успеха возвращает объект payments::Operation
# В случае неуспеха выставляет ошибку и возвращает undef.
# Сумма заказа в копейках
##########################################################
sub payment_operation_register {
    my $self = shift;
    my $opts = shift // {};
    unless ( $opts->{order_id} && $opts->{uid} && $opts->{sum} && $opts->{name} ) {
	$self->{result}{error} = 'Переданы не все обязательные параметры';
	return undef;
    }
    
    my $operation = $keeper->get_documents(
		class		=> 'payments::Operation',
		status		=> $self->{test_mode},
		order_id        => $opts->{order_id},
		order_by        => 'ctime',
		return_mode     => 'array_ref',
	);
    my $new = 0;
    if ( ref $operation eq 'ARRAY' && @$operation ) {
	my $last = $operation->[-1];
	if ( $opts->{name} eq 'create' && ($last->name eq 'suspend' || $last->name eq 'cancel' || $last->name eq 'close') ) {
		$self->{result}{error} = 'Заказ закрыт, отменен или заморожен. Оплата по нему невозможна';
		return undef;
	} elsif ( $opts->{name} eq 'refund' && ($last->name eq 'suspend' || $last->name eq 'close') ) {
		$self->{result}{error} = 'Заказ закрыт или заморожен. Возврат средств по нему невозможен';
		return undef;
	} elsif ( $last->name eq $opts->{name} ) {
		$operation = $last;
	} else {
		if ( $opts->{name} eq 'refund' && (grep { $_->name eq 'create' } @$operation) ) {
			$new = 1;
		}
	}
    } elsif ( $opts->{name} eq 'create' ) {
	$new = 1;
    }
    if ( $new ) {
	$operation = payments::Operation->new( $keeper );
	$operation->status( $self->{test_mode} );
	$operation->name( $opts->{name} );
	$operation->order_id( $opts->{order_id} );
	$operation->uid( $opts->{uid} );
	$operation->sum( $opts->{sum} );
	$operation->store;
    }
    return $operation;
}

sub get_transaction_by_order_id {
    my $self = shift;
    my $order_id = shift;

    my ($transaction) = $keeper->get_documents(
			class   => 'payments::Transaction',
			status  => $self->{test_mode},
			limit   => 1,
			order_id        => $order_id,
			order_by	=> 'ctime desc',
			provider        => $self->{payment_system},
		);

    return $transaction;
}

1;