Revision 358
- Date:
- 2013/06/11 08:56:08
- Files:
-
- /utf8/plugins/payments/comps
- /utf8/plugins/payments/comps/contenido
- /utf8/plugins/payments/comps/contenido/payments
- /utf8/plugins/payments/comps/contenido/payments/autohandler (Diff) (Checkout)
- /utf8/plugins/payments/comps/contenido/payments/dhandler (Diff) (Checkout)
- /utf8/plugins/payments/comps/contenido/payments/index.html (Diff) (Checkout)
- /utf8/plugins/payments/comps/www
- /utf8/plugins/payments/comps/www/payment.backend
- /utf8/plugins/payments/comps/www/payment.backend/moneta_check.xml (Diff) (Checkout)
- /utf8/plugins/payments/comps/www/payment.backend/moneta_pay.txt (Diff) (Checkout)
- /utf8/plugins/payments/comps/www/payment.backend/moneta_pay.xml (Diff) (Checkout)
- /utf8/plugins/payments/comps/www/payment.backend/xsolla_v2_pay.xml (Diff) (Checkout)
- /utf8/plugins/payments/config.proto (Diff) (Checkout)
- /utf8/plugins/payments/lib
- /utf8/plugins/payments/lib/payments
- /utf8/plugins/payments/lib/payments/Apache.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Init.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Keeper.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Operation.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Provider
- /utf8/plugins/payments/lib/payments/Provider/Base.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Provider/Moneta.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Provider/Xsolla.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/SQL
- /utf8/plugins/payments/lib/payments/SQL/OperationsTable.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/SQL/TransactionsTable.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/State.pm.proto (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/Transaction.pm (Diff) (Checkout)
- /utf8/plugins/payments/lib/payments/TransactionSection.pm (Diff) (Checkout)
- /utf8/plugins/payments/sql
- /utf8/plugins/payments/sql/TOAST
- /utf8/plugins/payments/sql/TOAST/operations.sql (Diff) (Checkout)
- /utf8/plugins/payments/sql/TOAST/transactions.sql (Diff) (Checkout)
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);