Revision 358

Date:
2013/06/11 08:56:08
Author:
ahitrov
Revision Log:
Initial plugin import
Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/plugins/payments/comps/contenido/payments/autohandler

     
    1 <%init>
    2
    3 $r->content_type('text/html');
    4 $m->call_next();
    5
    6 </%init>
  • utf8/plugins/payments/comps/contenido/payments/dhandler

     
    1 <& $call, %ARGS &>
    2 <%init>
    3
    4 my $call;
    5 if ( $r->uri eq '/contenido/payments/' ) {
    6 $call = 'index.html';
    7 } else {
    8 &abort404;
    9 }
    10
    11 </%init>
  • utf8/plugins/payments/comps/contenido/payments/index.html

     
    1 <& "/contenido/components/header.msn" &>
    2 <& "/contenido/components/naviline.msn" &>
    3
    4 <p>PLugin [payments]</p>
    5
    6 </body>
    7 </html>
  • utf8/plugins/payments/comps/www/payment.backend/moneta_check.xml

     
    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <MNT_RESPONSE>
    3 <MNT_ID><% $MNT_ID %></MNT_ID>
    4 <MNT_TRANSACTION_ID><% $MNT_TRANSACTION_ID %></MNT_TRANSACTION_ID>
    5 <MNT_RESULT_CODE><% $reply_code %></MNT_RESULT_CODE>
    6 % if ( ref $last ) {
    7 <MNT_DESCRIPTION><% $last->name %></MNT_DESCRIPTION>
    8 % }
    9 <MNT_AMOUNT><% $MNT_AMOUNT %></MNT_AMOUNT>
    10 <MNT_SIGNATURE><% $reply_md5 %></MNT_SIGNATURE>
    11 <%doc>
    12 <MNT_ATTRIBUTES>
    13 <ATTRIBUTE>
    14 <KEY></KEY>
    15 <VALUE></VALUE>
    16 </ATTRIBUTE>
    17 </MNT_ATTRIBUTES>
    18 </%doc>
    19 </MNT_RESPONSE>
    20 <%once>
    21
    22 use Digest::MD5;
    23
    24 </%once>
    25 <%args>
    26
    27 $MNT_COMMAND => ''
    28 $MNT_ID => undef
    29 $MNT_TRANSACTION_ID => undef
    30 $MNT_OPERATION_ID => ''
    31 $MNT_AMOUNT => ''
    32 $MNT_CURRENCY_CODE => undef
    33 $MNT_TEST_MODE => 0
    34 $MNT_SIGNATURE => undef
    35 $MNT_USER => undef
    36 $MNT_CORRACCOUNT => undef
    37 $MNT_CUSTOM1 => undef
    38 $MNT_CUSTOM2 => undef
    39 $MNT_CUSTOM3 => undef
    40
    41 </%args>
    42 <%init>
    43
    44 warn Dumper \%ARGS if $DEBUG;
    45 unless ( $MNT_ID && $MNT_TRANSACTION_ID && $MNT_CURRENCY_CODE ) {
    46 $m->out('FAIL');
    47 return;
    48 }
    49
    50 my $str = $MNT_COMMAND . $MNT_ID . $MNT_TRANSACTION_ID . $MNT_OPERATION_ID . $MNT_AMOUNT . $MNT_CURRENCY_CODE . $MNT_TEST_MODE . $state->{monetaru}->{moneta_sig_code};
    51 my $md5 = Digest::MD5::md5_hex ( $str );
    52 warn "MD5 Check: $md5\n" if $DEBUG;
    53 unless ( $MNT_SIGNATURE eq $md5 ) {
    54 $m->out('FAIL');
    55 return;
    56 }
    57
    58 my $reply_code;
    59 my $last = $keeper->{monetaru}->check( $MNT_TRANSACTION_ID );
    60 if ( ref $last ) {
    61 my $sum = sprintf("%.2f", $last->sum);
    62 if ( $last->name eq 'cancel' ) {
    63 $reply_code = 500;
    64 } elsif ( !$MNT_AMOUNT && $last->name =~ /(create|reform)/ ) {
    65 $MNT_AMOUNT = $last->sum;
    66 $reply_code = 100;
    67 } elsif ( $last->name =~ /(create|reform)/ && $sum ne $MNT_AMOUNT ) {
    68 $MNT_AMOUNT = $last->sum;
    69 $reply_code = 100;
    70 } elsif ( $last->name eq 'suspend' ) {
    71 $reply_code = 302;
    72 }
    73 } else {
    74 $reply_code = 500;
    75 }
    76
    77 unless ( $reply_code ) {
    78 my ($obj) = $keeper->get_documents(
    79 class => 'monetaru::Transaction',
    80 order_id => $MNT_TRANSACTION_ID,
    81 limit => 1,
    82 );
    83 if ( ref $obj ) {
    84 $reply_code = 200;
    85 } else {
    86 $reply_code = 402;
    87 }
    88 }
    89 warn "CHECK_URL: Reply code = [$reply_code]\n" if $DEBUG;
    90
    91 $str = $reply_code . $MNT_ID . $MNT_TRANSACTION_ID . $state->{monetaru}->{moneta_sig_code};
    92 my $reply_md5 = Digest::MD5::md5_hex ( $str );
    93 warn "Reply MD5: $reply_md5\n" if $DEBUG;
    94
    95 </%init>
  • utf8/plugins/payments/comps/www/payment.backend/moneta_pay.txt

     
    1 SUCCESS
    2 <%once>
    3
    4 use Digest::MD5;
    5
    6 </%once>
    7 <%args>
    8
    9 $MNT_ID => undef
    10 $MNT_TRANSACTION_ID => undef
    11 $MNT_OPERATION_ID => undef
    12 $MNT_AMOUNT => 0
    13 $MNT_CURRENCY_CODE => undef
    14 $MNT_TEST_MODE => 0
    15 $MNT_SIGNATURE => undef
    16 $MNT_USER => undef
    17 $MNT_CORRACCOUNT => undef
    18 $MNT_CUSTOM1 => undef
    19 $MNT_CUSTOM2 => undef
    20 $MNT_CUSTOM3 => undef
    21
    22 </%args>
    23 <%init>
    24
    25 warn Dumper \%ARGS if $DEBUG;
    26 unless ( $MNT_ID && $MNT_TRANSACTION_ID && $MNT_OPERATION_ID && $MNT_AMOUNT && $MNT_CURRENCY_CODE ) {
    27 $m->out('FAIL');
    28 return;
    29 }
    30
    31 my ($obj) = $keeper->get_documents(
    32 class => 'monetaru::Transaction',
    33 operation_id => $MNT_OPERATION_ID,
    34 order_id => $MNT_TRANSACTION_ID,
    35 limit => 1,
    36 );
    37 my $str = $MNT_ID . $MNT_TRANSACTION_ID . $MNT_OPERATION_ID . $MNT_AMOUNT . $MNT_CURRENCY_CODE . $MNT_TEST_MODE . $state->{monetaru}->{moneta_sig_code};
    38 my $md5 = Digest::MD5::md5_hex ( $str );
    39 unless ( $MNT_SIGNATURE eq $md5 ) {
    40 $m->out('FAIL');
    41 return;
    42 }
    43
    44 unless ( $obj ) {
    45 $obj = monetaru::Transaction->new( $keeper );
    46 $obj->status( $MNT_TEST_MODE || 0 );
    47 $obj->account_id( $MNT_ID );
    48 $obj->order_id( $MNT_TRANSACTION_ID );
    49 $obj->operation_id( $MNT_OPERATION_ID );
    50 $obj->sum( $MNT_AMOUNT );
    51 $obj->currency_code( $MNT_CURRENCY_CODE );
    52 $obj->account_user( $MNT_USER );
    53 $obj->account_corr( $MNT_CORRACCOUNT );
    54 $obj->payment_system( $ARGS{'paymentSystem.unitId'} );
    55 $obj->name( $MNT_CUSTOM1 );
    56 $obj->custom1( $MNT_CUSTOM1 );
    57 $obj->custom2( $MNT_CUSTOM2 );
    58 $obj->custom3( $MNT_CUSTOM3 );
    59 $obj->store;
    60 }
    61
    62 </%init>
  • utf8/plugins/payments/comps/www/payment.backend/moneta_pay.xml

     
    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <MNT_RESPONSE>
    3 <MNT_ID><% $MNT_ID %></MNT_ID>
    4 <MNT_TRANSACTION_ID><% $MNT_TRANSACTION_ID %></MNT_TRANSACTION_ID>
    5 <MNT_RESULT_CODE><% $reply_code %></MNT_RESULT_CODE>
    6 <MNT_SIGNATURE><% $reply_md5 %></MNT_SIGNATURE>
    7 <%doc>
    8 <MNT_ATTRIBUTES>
    9 <ATTRIBUTE>
    10 <KEY></KEY>
    11 <VALUE></VALUE>
    12 </ATTRIBUTE>
    13 </MNT_ATTRIBUTES>
    14 </%doc>
    15 </MNT_RESPONSE>
    16 <%once>
    17
    18 use Digest::MD5;
    19
    20 </%once>
    21 <%args>
    22
    23 $MNT_ID => undef
    24 $MNT_TRANSACTION_ID => undef
    25 $MNT_OPERATION_ID => undef
    26 $MNT_AMOUNT => ''
    27 $MNT_CURRENCY_CODE => undef
    28 $MNT_TEST_MODE => 0
    29 $MNT_SIGNATURE => undef
    30 $MNT_USER => undef
    31 $MNT_CORRACCOUNT => undef
    32 $MNT_CUSTOM1 => undef
    33 $MNT_CUSTOM2 => undef
    34 $MNT_CUSTOM3 => undef
    35
    36 </%args>
    37 <%init>
    38
    39 warn Dumper \%ARGS if $DEBUG;
    40 unless ( $MNT_ID && $MNT_TRANSACTION_ID && $MNT_OPERATION_ID && $MNT_AMOUNT && $MNT_CURRENCY_CODE ) {
    41 $m->out('FAIL');
    42 return;
    43 }
    44
    45 my $str = $MNT_ID . $MNT_TRANSACTION_ID . $MNT_OPERATION_ID . $MNT_AMOUNT . $MNT_CURRENCY_CODE . $MNT_TEST_MODE . $state->{monetaru}->{moneta_sig_code};
    46 my $md5 = Digest::MD5::md5_hex ( $str );
    47 unless ( $MNT_SIGNATURE eq $md5 ) {
    48 $m->out('FAIL');
    49 return;
    50 }
    51
    52 my $reply_code;
    53 my $last = $keeper->{monetaru}->check( $MNT_TRANSACTION_ID );
    54 if ( ref $last ) {
    55 my $sum = sprintf("%.2f", $last->sum);
    56 if ( $last->name eq 'cancel' ) {
    57 $reply_code = 500;
    58 } elsif ( $last->name eq 'suspend' ) {
    59 $reply_code = 500;
    60 }
    61 } else {
    62 $reply_code = 500;
    63 }
    64
    65 unless ( $reply_code ) {
    66 my ($obj) = $keeper->get_documents(
    67 class => 'monetaru::Transaction',
    68 operation_id => $MNT_OPERATION_ID,
    69 order_id => $MNT_TRANSACTION_ID,
    70 limit => 1,
    71 );
    72
    73 unless ( $obj ) {
    74 $obj = monetaru::Transaction->new( $keeper );
    75 $obj->status( $MNT_TEST_MODE || 0 );
    76 $obj->account_id( $MNT_ID );
    77 $obj->order_id( $MNT_TRANSACTION_ID );
    78 $obj->operation_id( $MNT_OPERATION_ID );
    79 $obj->sum( $MNT_AMOUNT );
    80 $obj->currency_code( $MNT_CURRENCY_CODE );
    81 $obj->account_user( $MNT_USER );
    82 $obj->account_corr( $MNT_CORRACCOUNT );
    83 $obj->payment_system( $ARGS{'paymentSystem.unitId'} );
    84 $obj->name( $MNT_CUSTOM1 );
    85 $obj->custom1( $MNT_CUSTOM1 );
    86 $obj->custom2( $MNT_CUSTOM2 );
    87 $obj->custom3( $MNT_CUSTOM3 );
    88 $obj->store;
    89 }
    90 if ( $obj->id ) {
    91 $reply_code = 200;
    92 } else {
    93 $reply_code = 100;
    94 }
    95 }
    96
    97 $str = $reply_code . $MNT_ID . $MNT_TRANSACTION_ID . $state->{monetaru}->{moneta_sig_code};
    98 my $reply_md5 = Digest::MD5::md5_hex ( $str );
    99
    100 </%init>
  • utf8/plugins/payments/comps/www/payment.backend/xsolla_v2_pay.xml

     
    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <response>
    3 <result><% $code %></result>
    4 <description><% $codes{$code} %></description>
    5 <fields>
    6 <id><% $id %></id>
    7 <order><% $v1 %></order>
    8 <amount><% $amount %></amount>
    9 <currency><% $currency %></currency>
    10 <datetime><% $datetime %></datetime>
    11 <sign><% $sign %></sign>
    12 </fields>
    13 </response>
    14 <%doc>
    15
    16 сommand Признак того, что идет оповещение о платеже
    17 id Уникальный id операции в системе «Иксолла»
    18 v1 Уникальный идентификатор заказа, полученный от проекта. В XML-ответе значение этого параметра следует передававть в параметре order.
    19 amount Стоимость заказа. Разделитель “.” (2 знака после точки)
    20 currency Валюта заказа. Используется трехбуквенное обозначение валюты согласно стандарту ISO 4217
    21 datetime Дата в формате ГГГГММДДЧЧММСС
    22 test Признак тестовой транзакции. test=1 – система проводит тестовую транзакцию. Реального платежа не было. test=0 – реальный платеж
    23 sign Подпись для предотвращения несанкционированного доступа
    24 user_sum Размер платежа, совершенного пользователем. Разделитель “.” (2 знака после точки)
    25 user_currency Валюта платежа, совершенного пользователем. Используется трехбуквенное обозначение валюты согласно стандарту ISO 4217
    26 transfer_sum Сумма выплаты проекту. Разделитель “.” (2 знака после точки)
    27 transfer_currency Валюта выплаты проекту. Используется трехбуквенное обозначение валюты согласно стандарту ISO 4217
    28 pid Идентификационный номер платежной системы
    29 id_geotype id валюты платежной системы
    30
    31 </%doc>
    32 <%once>
    33
    34 use Digest::MD5;
    35 my @valid_ips = qw( 94.103.26.178 94.103.26.181 159.255.220.254 );
    36 my %codes = (
    37 '0' => 'Success',
    38 '10' => 'Another delivery attempt',
    39 '20' => 'Wrong parameters',
    40 '30' => 'Temporary error',
    41 '40' => 'Fatal error',
    42 );
    43
    44 </%once>
    45 <%args>
    46
    47 $id => undef
    48 $v1 => ''
    49 $v2 => ''
    50 $v3 => ''
    51 $amount => undef
    52 $currency => undef
    53 $datetime => undef
    54 $test => undef
    55 $sign => undef
    56 $user_sum => undef
    57 $user_currency => undef
    58 $transfer_sum => undef
    59 $transfer_currency => undef
    60 $pid => undef
    61 $id_geotype => undef
    62
    63 </%args>
    64 <%init>
    65
    66 warn Dumper \%ARGS if $DEBUG;
    67
    68 my $str = $v1.$v2.$v3.$amount.$currency.$id.$state->{payments}{xsolla_app_secret};
    69 my $md5 = Digest::MD5::md5_hex ( $str );
    70 warn "MD5 Check: $md5\n" if $DEBUG;
    71
    72 my $code = 0;
    73 my $ip = $r->header_in('X-Real-IP');
    74 warn "From IP=$ip\n";
    75 my $transaction;
    76 if ( $md5 eq $sign && grep { $ip eq $_ } @valid_ips ) {
    77 my $last = $keeper->{payments}->check( $v1 );
    78 if ( $last->name eq 'cancel' ) {
    79 $code = 40;
    80 } elsif ( $last->name eq 'suspend' ) {
    81 $code = 20;
    82 }
    83 unless ( $code ) {
    84 ($transaction) = $keeper->get_documents(
    85 class => 'payments::Transaction',
    86 order_id => $v1,
    87 operation_id => $id,
    88 provider => 'xsolla',
    89 limit => 1,
    90 );
    91 if ( ref $transaction ) {
    92 $code = 10;
    93 } else {
    94 my $dt = $datetime =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ? "$1-$2-$3 $4:$5:$6" : '';
    95 $transaction = payments::Transaction->new( $keeper );
    96 $transaction->status( $test || 0 );
    97 $transaction->provider( 'xsolla' );
    98 $transaction->order_id( $v1 );
    99 $transaction->operation_id( $id );
    100 $transaction->sum( $amount );
    101 $transaction->currency_code( $currency );
    102 $transaction->dtime( $dt ) if $dt;
    103 $transaction->custom1( $v2 );
    104 $transaction->custom2( $v3 );
    105 $transaction->name( $v2 || $v3 );
    106 $transaction->store();
    107 }
    108 }
    109 } else {
    110 $code = 20;
    111 }
    112
    113 </%init>
  • utf8/plugins/payments/config.proto

     
    1 #############################################################################
    2 #
    3 # Параметры данного шаблона необходимо ВРУЧНУЮ добавить в config.mk проекта
    4 # и привести в соответствие с требованиями проекта
    5 #
    6 #############################################################################
    7 PLUGINS += payments
    8
    9 # Moneta.ru
    10 ############################################################
    11 MNT_ID =
    12 MNT_SECRET =
    13 MNT_CURRENCY_CODE = RUB
    14 MNT_TEST_MODE = 1 # 0 - для боевого режима
    15 # Для подтверждения целостности
    16 MNT_SIG_CODE =
    17
    18 REWRITE += MNT_ID MNT_SECRET MNT_CURRENCY_CODE MNT_TEST_MODE MNT_SIG_CODE
    19 ############################################################
    20 # /Moneta.ru
    21
    22
    23 # xsolla.com
    24 ############################################################
    25 XSO_ID =
    26 XSO_SECRET =
    27 XSO_CURRENCY_CODE = RUB
    28 XSO_TEST_MODE = 1 # 0 - для боевого режима
    29 # Для подтверждения целостности
    30 XSO_SIG_CODE =
    31
    32 REWRITE += XSO_ID XSO_SECRET XSO_CURRENCY_CODE XSO_TEST_MODE XSO_SIG_CODE
    33 ############################################################
    34 # /xsolla.com
    35
  • utf8/plugins/payments/lib/payments/Apache.pm

     
    1 package payments::Apache;
    2
    3 use strict;
    4 use warnings 'all';
    5
    6 use payments::State;
    7 use Contenido::Globals;
    8
    9
    10 sub child_init {
    11 # встраиваем keeper плагина в keeper проекта
    12 $keeper->{payments} = payments::Keeper->new($state->payments);
    13 }
    14
    15 sub request_init {
    16 }
    17
    18 sub child_exit {
    19 }
    20
    21 1;
  • utf8/plugins/payments/lib/payments/Init.pm

     
    1 package payments::Init;
    2
    3 use strict;
    4 use warnings 'all';
    5
    6 use Contenido::Globals;
    7 use payments::Apache;
    8 use payments::Keeper;
    9
    10 use payments::Provider::Base;
    11
    12 # загрузка всех необходимых плагину классов
    13 # payments::SQL::SomeTable
    14 # payments::SomeClass
    15 Contenido::Init::load_classes(qw(
    16 payments::SQL::TransactionsTable
    17 payments::Transaction
    18
    19 payments::SQL::OperationsTable
    20 payments::Operation
    21
    22 payments::TransactionSection
    23
    24 payments::Provider::Base
    25 payments::Provider::Moneta
    26 payments::Provider::Xsolla
    27 ));
    28
    29 sub init {
    30 push @{ $state->{'available_documents'} }, qw( payments::Transaction payments::Operation );
    31 push @{ $state->{'available_sections'} }, qw( payments::TransactionSection );
    32 0;
    33 }
    34
    35 1;
  • utf8/plugins/payments/lib/payments/Keeper.pm

     
    1 package payments::Keeper;
    2
    3 use strict;
    4 use warnings 'all';
    5 use base qw(Contenido::Keeper);
    6
    7
    8 use Contenido::Globals;
    9
    10 sub add {
    11 my $self = shift;
    12 my (%opts) = @_;
    13
    14 return undef unless $opts{type} && ( $opts{order} && ref $opts{order} || $opts{uid} && $opts{order} && $opts{sum});
    15 return undef unless $opts{type} =~ /^(create|suspend|cancel|append|reform)$/;
    16
    17 my $op = payments::Operation->new( $keeper );
    18 $op->status(1);
    19 $op->name( $opts{type} );
    20 if ( ref $opts{order} ) {
    21 $op->uid( $opts{order}->uid );
    22 $op->order_id( $opts{order}->id );
    23 $op->sum( $opts{order}->sum_total );
    24 } else {
    25 $op->uid( $opts{uid} );
    26 $op->order_id( $opts{order} );
    27 $op->sum( $opts{sum} );
    28 }
    29 $op->store;
    30
    31 return $op;
    32 }
    33
    34
    35 sub check {
    36 my $self = shift;
    37 my $order_id = shift;
    38 return undef unless $order_id;
    39
    40 my $ops = $keeper->get_documents(
    41 class => 'payments::Operation',
    42 order_id => $order_id,
    43 order_by => 'ctime',
    44 return_mode => 'array_ref',
    45 );
    46 if ( ref $ops eq 'ARRAY' && @$ops ) {
    47 return $ops->[-1];
    48 }
    49 return undef;
    50 }
    51
    52
    53 1;
  • utf8/plugins/payments/lib/payments/Operation.pm

     
    1 package payments::Operation;
    2
    3 use base "Contenido::Document";
    4 sub extra_properties
    5 {
    6 return (
    7 { 'attr' => 'name', 'type' => 'status', 'rusname' => 'Тип операции',
    8 'cases' => [
    9 ['create', 'Заказ создан'],
    10 ['suspend', 'Заказ заморожен'],
    11 ['reform', 'Заказ изменен'],
    12 ['append', 'Доплата по заказу'],
    13 ['cancel', 'Заказ отменен'],
    14 ],
    15 },
    16 )
    17 }
    18
    19 sub class_name
    20 {
    21 return 'Payments: операция с заказом';
    22 }
    23
    24 sub class_description
    25 {
    26 return 'Payments: операция с заказом';
    27 }
    28
    29 sub class_table
    30 {
    31 return 'payments::SQL::OperationsTable';
    32 }
    33
    34 1;
  • utf8/plugins/payments/lib/payments/Provider/Base.pm

     
    1 package payments::Provider::Base;
    2
    3 use strict;
    4 use warnings 'all';
    5 use Contenido::Globals;
    6 use payments::Keeper;
    7
    8
    9 sub new {
    10 my ($proto, %params) = @_;
    11 my $class = ref($proto) || $proto;
    12 my $self = {};
    13 my $prefix = $class =~ /\:\:(\w+)$/ ? lc($1) : undef;
    14 return unless $prefix;
    15
    16 $self->{payment_system} = $prefix;
    17 $self->{app_id} = $state->{payments}->{$prefix."_app_id"};
    18 $self->{secret} = $state->{payments}->{$prefix."_app_secret"};
    19 $self->{currency} = $state->{payments}->{$prefix."_currency_code"};
    20 $self->{test_mode} = $state->{payments}->{$prefix."_test_mode"};
    21
    22 bless $self, $class;
    23
    24 return $self;
    25 }
    26
    27
    28 sub id {
    29 my $self = shift;
    30 return $self->{app_id};
    31 }
    32
    33 sub app_id {
    34 my $self = shift;
    35 return $self->{app_id};
    36 }
    37
    38 sub secret {
    39 my $self = shift;
    40 return $self->{secret};
    41 }
    42
    43 sub test_mode {
    44 my $self = shift;
    45 return $self->{test_mode};
    46 }
    47
    48 sub currency {
    49 my $self = shift;
    50 return $self->{currency};
    51 }
    52
    53 sub currency_code {
    54 my $self = shift;
    55 return $self->{currency};
    56 }
    57
    58 sub payment_system {
    59 my $self = shift;
    60 return $self->{payment_system};
    61 }
    62
    63 1;
  • utf8/plugins/payments/lib/payments/Provider/Moneta.pm

     
    1 package payments::Provider::Base;
    2
    3 use strict;
    4 use warnings 'all';
    5
    6 use base 'payments::Provider::Base';
    7 use Contenido::Globals;
    8 use payments::Keeper;
    9 use Digest::MD5;
    10 use Data::Dumper;
    11
    12 sub get_form {
    13 my $self = shift;
    14 my (%opts) = @_;
    15 my $id = delete $opts{id};
    16 return unless $id;
    17 my $sum = delete $opts{sum};
    18 return unless $sum;
    19
    20 $sum = $sum =~ /\d+\.\d{2}/ ? $sum : sprintf( "%.2f", $sum );
    21
    22 my %fields = (
    23 'method' => 'post',
    24 'action' => 'https://www.moneta.ru/assistant.htm',
    25 'visible' => [
    26 { type => 'submit', value => $opts{submit} || 'Оплатить' },
    27 ],
    28 'hidden' => [
    29 { name => 'MNT_ID', value => $state->{payments}{moneta_app_id} },
    30 { name => 'MNT_TRANSACTION_ID', value => $id },
    31 { name => 'MNT_CURRENCY_CODE', value => $state->{payments}{moneta_currency_code} },
    32 { name => 'MNT_AMOUNT', value => $sum },
    33 ],
    34 );
    35 if ( $state->{payments}{moneta_test_mode} ) {
    36 push @{$fields{hidden}}, { name => 'MNT_TEST_MODE', value => 1 }
    37 }
    38 if ( $opts{success} ) {
    39 push @{$fields{hidden}}, { name => 'MNT_SUCCESS_URL', value => $opts{success} }
    40 }
    41 if ( $opts{fail} ) {
    42 push @{$fields{hidden}}, { name => 'MNT_FAIL_URL', value => $opts{fail} }
    43 }
    44 if ( $state->{payments}{moneta_sig_code} ) {
    45 my $str = $state->{payments}{moneta_app_id}.$id.$sum.$state->{payments}{moneta_currency_code}.$state->{payments}{moneta_test_mode}.$state->{payments}{moneta_sig_code};
    46 my $md5 = Digest::MD5::md5_hex ( $str );
    47 push @{$fields{hidden}}, { name => 'MNT_SIGNATURE', value => $md5 }
    48 }
    49
    50 if ( exists $opts{custom1} ) {
    51 push @{$fields{hidden}}, { name => 'MNT_CUSTOM1', value => $opts{custom1} }
    52 }
    53 if ( exists $opts{custom2} ) {
    54 push @{$fields{hidden}}, { name => 'MNT_CUSTOM2', value => $opts{custom2} }
    55 }
    56 if ( exists $opts{custom3} ) {
    57 push @{$fields{hidden}}, { name => 'MNT_CUSTOM3', value => $opts{custom3} }
    58 }
    59
    60 return \%fields;
    61 }
    62
    63
    64 1;
  • utf8/plugins/payments/lib/payments/Provider/Xsolla.pm

     
    1 package payments::Provider::Xsolla;
    2
    3 use strict;
    4 use warnings 'all';
    5
    6 use base 'payments::Provider::Base';
    7 use Contenido::Globals;
    8 use payments::Keeper;
    9 use Digest::MD5;
    10 use Data::Dumper;
    11
    12
    13 sub get_iframe {
    14 my $self = shift;
    15 my (%opts) = @_;
    16 my $id = delete $opts{id};
    17 return unless $id;
    18 my $sum = delete $opts{sum};
    19 return unless $sum;
    20
    21 $sum = $sum =~ /\d+\.\d{2}/ ? $sum : sprintf( "%.2f", $sum );
    22 my @params = (
    23 'marketplace=paydesk',
    24 'theme=115',
    25 'project='.$state->{payments}{xsolla_app_id},
    26 'local=ru',
    27 'pid=26',
    28 'v1='.$id,
    29 );
    30 my $iframe = '<iframe id="paystation" src="https://secure.xsolla.com/paystation2/?'.join('&',@params).'" width="100%" height="100%">';
    31 return $iframe;
    32 }
    33
    34
    35 1;
  • utf8/plugins/payments/lib/payments/SQL/OperationsTable.pm

     
    1 package payments::SQL::OperationsTable;
    2
    3 use base 'SQL::DocumentTable';
    4
    5 sub db_table
    6 {
    7 return 'payments_operations';
    8 }
    9
    10
    11 sub available_filters {
    12 my @available_filters = qw(
    13
    14 _class_filter
    15 _status_filter
    16 _in_id_filter
    17 _id_filter
    18 _name_filter
    19 _class_excludes_filter
    20 _sfilter_filter
    21 _excludes_filter
    22 _datetime_filter
    23 _date_equal_filter
    24 _date_filter
    25 _previous_days_filter
    26
    27 _order_id_filter
    28 _uid_filter
    29 );
    30
    31 return \@available_filters;
    32 }
    33
    34 # ----------------------------------------------------------------------------
    35 # Свойства храним в массивах, потому что порядок важен!
    36 # Это общие свойства - одинаковые для всех документов.
    37 #
    38 # attr - обязательный параметр, название атрибута;
    39 # type - тип аттрибута, требуется для отображдения;
    40 # rusname - русское название, опять же требуется для отображения;
    41 # hidden - равен 1, когда
    42 # readonly - инициализации при записи только без изменения в дальнейшем
    43 # db_field - поле в таблице
    44 # default - значение по умолчанию (поле всегда имеет это значение)
    45 # ----------------------------------------------------------------------------
    46 sub required_properties
    47 {
    48 my $self = shift;
    49
    50 my @parent_properties = grep { $_->{attr} ne 'dtime' && $_->{attr} ne 'sections' } $self->SUPER::required_properties;
    51 return (
    52 @parent_properties,
    53 {
    54 'attr' => 'uid',
    55 'type' => 'integer',
    56 'rusname' => 'ID пользователя',
    57 'db_field' => 'uid',
    58 'db_type' => 'integer',
    59 'db_opts' => "default 0",
    60 },
    61 { # ID заказа
    62 'attr' => 'order_id',
    63 'type' => 'integer',
    64 'rusname' => 'ID заказа',
    65 'db_field' => 'order_id',
    66 'db_type' => 'integer',
    67 'db_opts' => "not null",
    68 },
    69 {
    70 'attr' => 'sum',
    71 'type' => 'string',
    72 'rusname' => 'Сумма',
    73 'db_field' => 'sum',
    74 'db_type' => 'float',
    75 },
    76 );
    77 }
    78
    79
    80 ########### FILTERS DESCRIPTION ###############################################################################
    81 sub _uid_filter {
    82 my ($self,%opts)=@_;
    83 return undef unless ( exists $opts{uid} );
    84 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid});
    85 }
    86
    87 sub _order_id_filter {
    88 my ($self,%opts)=@_;
    89 return undef unless ( exists $opts{order_id} );
    90 return &SQL::Common::_generic_int_filter('d.order_id', $opts{order_id});
    91 }
    92
    93 1;
  • utf8/plugins/payments/lib/payments/SQL/TransactionsTable.pm

     
    1 package payments::SQL::TransactionsTable;
    2
    3 use base 'SQL::DocumentTable';
    4
    5 sub db_table
    6 {
    7 return 'payments_transactions';
    8 }
    9
    10
    11 sub available_filters {
    12 my @available_filters = qw(
    13
    14 _class_filter
    15 _status_filter
    16 _in_id_filter
    17 _id_filter
    18 _name_filter
    19 _class_excludes_filter
    20 _sfilter_filter
    21 _excludes_filter
    22 _datetime_filter
    23 _date_equal_filter
    24 _date_filter
    25 _previous_days_filter
    26
    27 _operation_id_filter
    28 _order_id_filter
    29 _provider_filter
    30 );
    31
    32 return \@available_filters;
    33 }
    34
    35 # ----------------------------------------------------------------------------
    36 # Свойства храним в массивах, потому что порядок важен!
    37 # Это общие свойства - одинаковые для всех документов.
    38 #
    39 # attr - обязательный параметр, название атрибута;
    40 # type - тип аттрибута, требуется для отображдения;
    41 # rusname - русское название, опять же требуется для отображения;
    42 # hidden - равен 1, когда
    43 # readonly - инициализации при записи только без изменения в дальнейшем
    44 # db_field - поле в таблице
    45 # default - значение по умолчанию (поле всегда имеет это значение)
    46 # ----------------------------------------------------------------------------
    47 sub required_properties
    48 {
    49 my $self = shift;
    50
    51 my @parent_properties = grep { $_->{attr} ne 'sections' } $self->SUPER::required_properties;
    52 return (
    53 @parent_properties,
    54 {
    55 'attr' => 'provider',
    56 'type' => 'string',
    57 'rusname' => 'Провайдер',
    58 'db_field' => 'provider',
    59 'db_type' => 'text',
    60 },
    61 {
    62 'attr' => 'account_id',
    63 'type' => 'integer',
    64 'rusname' => 'Аккаунт',
    65 'db_field' => 'account_id',
    66 'db_type' => 'numeric',
    67 'db_opts' => "default 0",
    68 },
    69 { # ID заказа
    70 'attr' => 'order_id',
    71 'type' => 'integer',
    72 'rusname' => 'ID заказа',
    73 'db_field' => 'order_id',
    74 'db_type' => 'integer',
    75 'db_opts' => "not null",
    76 },
    77 { # ID заказа
    78 'attr' => 'operation_id',
    79 'type' => 'integer',
    80 'rusname' => 'ID транзакции',
    81 'db_field' => 'operation_id',
    82 'db_type' => 'numeric',
    83 'db_opts' => "not null",
    84 },
    85 {
    86 'attr' => 'currency_code',
    87 'type' => 'string',
    88 'rusname' => 'ID валюты',
    89 'db_field' => 'currency_code',
    90 'db_type' => 'varchar(4)',
    91 },
    92 {
    93 'attr' => 'sum',
    94 'type' => 'string',
    95 'rusname' => 'Сумма платежа',
    96 'db_field' => 'sum',
    97 'db_type' => 'float',
    98 },
    99 {
    100 'attr' => 'account_user',
    101 'type' => 'string',
    102 'rusname' => 'Номер счета пользователя',
    103 'db_field' => 'account_user',
    104 'db_type' => 'text',
    105 },
    106 {
    107 'attr' => 'account_corr',
    108 'type' => 'string',
    109 'rusname' => 'Номер счета плательщика',
    110 'db_field' => 'account_corr',
    111 'db_type' => 'text',
    112 },
    113 {
    114 'attr' => 'payment_system',
    115 'type' => 'string',
    116 'rusname' => 'Идентификатор платежной системы',
    117 'db_field' => 'payment_system',
    118 'db_type' => 'text',
    119 },
    120 );
    121 }
    122
    123
    124 ########### FILTERS DESCRIPTION ###############################################################################
    125 sub _operation_id_filter {
    126 my ($self,%opts)=@_;
    127 return undef unless ( exists $opts{operation_id} );
    128 return &SQL::Common::_generic_int_filter('d.operation_id', $opts{operation_id});
    129 }
    130
    131 sub _order_id_filter {
    132 my ($self,%opts)=@_;
    133 return undef unless ( exists $opts{order_id} );
    134 return &SQL::Common::_generic_int_filter('d.order_id', $opts{order_id});
    135 }
    136
    137 sub _provider_filter {
    138 my ($self,%opts)=@_;
    139 return undef unless ( exists $opts{provider} );
    140 return &SQL::Common::_generic_text_filter('d.provider', $opts{provider});
    141 }
    142
    143 1;
  • utf8/plugins/payments/lib/payments/State.pm.proto

     
    1 package payments::State;
    2
    3 use strict;
    4 use warnings 'all';
    5 use vars qw($AUTOLOAD);
    6
    7
    8 sub new {
    9 my ($proto) = @_;
    10 my $class = ref($proto) || $proto;
    11 my $self = {};
    12 bless $self, $class;
    13
    14 # configured
    15 $self->{debug} = (lc('') eq 'yes');
    16 $self->{project} = '';
    17
    18 # зашитая конфигурация плагина
    19 $self->{db_type} = 'none'; ### For REAL database use 'remote'
    20 $self->{db_keepalive} = 0;
    21 $self->{db_host} = '';
    22 $self->{db_name} = '';
    23 $self->{db_user} = '';
    24 $self->{db_password} = '';
    25 $self->{db_port} = '';
    26 $self->{store_method} = 'toast';
    27 $self->{cascade} = 1;
    28 $self->{db_prepare} = 0;
    29
    30 $self->{memcached_enable} = lc( '' ) eq 'yes' ? 1 : 0;
    31 $self->{memcached_enable_compress} = 1;
    32 $self->{memcached_backend} = '';
    33 $self->{memcached_servers} = [qw()];
    34 $self->{memcached_busy_lock} = 60;
    35 $self->{memcached_delayed} = lc('') eq 'yes' ? 1 : 0;
    36
    37 $self->{serialize_with} = 'json'; ### or 'dumper'
    38
    39 # not implemented really (core compatibility)
    40 $self->{binary_directory} = '/nonexistent';
    41 $self->{data_directory} = '/nonexistent';
    42 $self->{images_directory} = '/nonexistent';
    43 $self->{preview} = '0';
    44
    45 $self->{moneta_app_id} = '@MNT_ID@';
    46 $self->{moneta_app_secret} = '@MNT_SECRET@';
    47 $self->{moneta_currency_code} = '@MNT_CURRENCY_CODE@';
    48 $self->{moneta_test_mode} = int('@MNT_TEST_MODE@' || 0);
    49 $self->{moneta_sig_code} = '@MNT_SIG_CODE@';
    50
    51 $self->{xsolla_app_id} = '@XSO_ID@';
    52 $self->{xsolla_app_secret} = '@XSO_SECRET@';
    53 $self->{xsolla_currency_code} = '@XSO_CURRENCY_CODE@';
    54 $self->{xsolla_test_mode} = int('@XSO_TEST_MODE@' || 0);
    55
    56 $self->_init_();
    57 $self;
    58 }
    59
    60 sub info {
    61 my $self = shift;
    62 return unless ref $self;
    63
    64 for (sort keys %{$self->{attributes}}) {
    65 my $la = length $_;
    66 warn "\t$_".("\t" x (2-int($la/8))).": $self->{$_}\n";
    67 }
    68 }
    69
    70 sub _init_ {
    71 my $self = shift;
    72
    73 # зашитая конфигурация плагина
    74 $self->{attributes}->{$_} = 'SCALAR' for qw(
    75 debug
    76 project
    77
    78 db_type
    79 db_keepalive
    80 db_host
    81 db_port
    82 db_name
    83 db_user
    84 db_password
    85 store_method
    86 cascade
    87 db_prepare
    88 db_client_encoding
    89
    90 memcached_enable
    91 memcached_enable_compress
    92 memcached_backend
    93 memcached_servers
    94 memcached_busy_lock
    95 memcached_delayed
    96
    97 binary_directory
    98 data_directory
    99 images_directory
    100 preview
    101 );
    102 }
    103
    104 sub AUTOLOAD {
    105 my $self = shift;
    106 my $attribute = $AUTOLOAD;
    107
    108 $attribute =~ s/.*:://;
    109 return unless $attribute =~ /[^A-Z]/; # Отключаем методы типа DESTROY
    110
    111 if (!exists $self->{attributes}->{$attribute}) {
    112 warn "Contenido Error (payments::State): Вызов метода, для которого не существует обрабатываемого свойства: ->$attribute()\n";
    113 return;
    114 }
    115
    116 $self->{$attribute} = shift @_ if $#_>=0;
    117 $self->{$attribute};
    118 }
    119
    120 1;
  • utf8/plugins/payments/lib/payments/Transaction.pm

     
    1 package payments::Transaction;
    2
    3 use base "Contenido::Document";
    4 sub extra_properties
    5 {
    6 return (
    7 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус тестирования',
    8 'cases' => [
    9 [0, 'Реальная оплата'],
    10 [1, 'Тестовая оплата'],
    11 ],
    12 },
    13 { 'attr' => 'custom1', 'type' => 'string', 'rusname' => 'Параметр 1' },
    14 { 'attr' => 'custom2', 'type' => 'string', 'rusname' => 'Параметр 2' },
    15 { 'attr' => 'custom3', 'type' => 'string', 'rusname' => 'Параметр 3' },
    16 )
    17 }
    18
    19 sub class_name
    20 {
    21 return 'Payments: транзакция';
    22 }
    23
    24 sub class_description
    25 {
    26 return 'Payments: транзакция';
    27 }
    28
    29 sub class_table
    30 {
    31 return 'payments::SQL::TransactionsTable';
    32 }
    33
    34 1;
  • utf8/plugins/payments/lib/payments/TransactionSection.pm

     
    1 package payments::TransactionSection;
    2
    3 use base 'Contenido::Section';
    4
    5 sub extra_properties
    6 {
    7 return (
    8 { 'attr' => 'brief', 'type' => 'text', 'rusname' => 'Описание секции' },
    9 { 'attr' => 'default_document_class', 'default' => 'payments::Transaction' },
    10 { 'attr' => '_sorted', 'hidden' => 1 },
    11 { 'attr' => 'order_by', 'hidden' => 1 },
    12 )
    13 }
    14
    15 sub class_name
    16 {
    17 return 'Payments: Секция транзакций';
    18 }
    19
    20 sub class_description
    21 {
    22 return 'Payments: Секция транзакций';
    23 }
    24
    25 1;
  • utf8/plugins/payments/sql/TOAST/operations.sql

     
    1 create table payments_operations
    2 (
    3 id integer not null primary key default nextval('public.documents_id_seq'::text),
    4 class text not null,
    5 ctime timestamp not null default now(),
    6 mtime timestamp not null default now(),
    7 status smallint not null default 0,
    8 name text,
    9 order_id integer not null,
    10 uid integer not null,
    11 sum float,
    12 data text
    13 );
    14 CREATE INDEX payments_operations_order ON payments_operations USING btree (order_id);
  • utf8/plugins/payments/sql/TOAST/transactions.sql

     
    1 create table payments_transactions
    2 (
    3 id integer not null primary key default nextval('public.documents_id_seq'::text),
    4 class text not null,
    5 ctime timestamp not null default now(),
    6 mtime timestamp not null default now(),
    7 dtime timestamp not null default now(),
    8 status smallint not null default 0,
    9 provider text,
    10 name text,
    11 account_id numeric,
    12 order_id integer not null,
    13 operation_id numeric not null,
    14 currency_code varchar(4),
    15 sum float,
    16 account_user text,
    17 payment_system text,
    18 account_corr text,
    19 data text
    20 );
    21 CREATE INDEX payments_transactions_operations ON payments_transactions USING btree (provider, operation_id);
    22 CREATE INDEX payments_transactions_orders ON payments_transactions USING btree (order_id);

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.