webmoney 0.0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ // stdafx.cpp : source file that includes just the standard includes
2
+ // wmsigner.pch will be the pre-compiled header
3
+ // stdafx.obj will contain the pre-compiled type information
4
+
5
+ #include "stdafx.h"
6
+
7
+ // TODO: reference any additional headers you need in STDAFX.H
8
+ // and not in this file
@@ -0,0 +1,33 @@
1
+ // stdafx.h : include file for standard system include files,
2
+ // or project specific include files that are used frequently, but
3
+ // are changed infrequently
4
+ //
5
+
6
+ // REMOVE COMMENT FOR DEBUG MODE
7
+ //#ifndef _DEBUG
8
+ //#define _DEBUG
9
+ //#endif
10
+
11
+
12
+ #include <stdio.h>
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+ #include <sys/types.h>
16
+ #include <errno.h>
17
+ #ifdef _WIN32
18
+ #pragma once
19
+ #include <iostream>
20
+ #include <tchar.h>
21
+ #include <windows.h>
22
+ #include <io.h>
23
+ #include <memory.h>
24
+ #pragma warning(disable : 4996)
25
+ #endif
26
+ // TODO: reference additional headers your program requires here
27
+ #ifndef TRUE
28
+ #define TRUE 1
29
+ #endif
30
+ #ifndef FALSE
31
+ #define FALSE 0
32
+ #endif
33
+
@@ -0,0 +1,119 @@
1
+ // Include the Ruby headers and goodies
2
+ #include <stdlib.h>
3
+ #include <ctype.h>
4
+ #include "ruby.h"
5
+ #include "signer.h"
6
+ #include "base64.h"
7
+ #include "cmdbase.h"
8
+
9
+ #define ASCII_SIZE 512
10
+ #define BUF_64_SIZE 220
11
+
12
+ // Defining a space for information and references about the module to be stored internally
13
+ VALUE cSigner;
14
+
15
+ typedef VALUE (ruby_method)(...);
16
+
17
+ // Prototype for the initialization method - Ruby calls this, not you
18
+ //extern "C" void Init_Wmutils();
19
+
20
+ // Prototype for our method 'test1' - methods are prefixed by 'method_' here
21
+ // typedef VALUE method_test1(VALUE self);
22
+ // typedef VALUE initialize(VALUE self, const char *szWMID, const char *szPwd, const char *szKeyData);
23
+
24
+ //Signer *pSign;
25
+
26
+ void signer_free(Signer *p)
27
+ {
28
+ if (p)
29
+ delete p;
30
+ }
31
+
32
+ bool IsWmid(const char* sz)
33
+ {
34
+ int len = strlen(sz);
35
+ if (len != 12) return false;
36
+ for(int i = 0; i < len; i++)
37
+ {
38
+ if (!isdigit(sz[i]))
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ extern "C" VALUE signer_new(VALUE self, VALUE szWMID, VALUE szPwd, VALUE szKeyData64)
45
+ {
46
+ Signer *pSign;
47
+
48
+ if(NIL_P(szWMID)) rb_raise(rb_eArgError, "nil wmid");
49
+
50
+ // check WMID
51
+ if (! IsWmid(RSTRING(szWMID)->ptr)) rb_raise(rb_eArgError, "Incorrect WMID");
52
+
53
+ if(NIL_P(szPwd)) rb_raise(rb_eArgError, "nil password");
54
+
55
+ if(NIL_P(szKeyData64)) rb_raise(rb_eArgError, "nil key");
56
+
57
+ // check base64 data
58
+ if ( RSTRING(szKeyData64)->len != 220 ) rb_raise(rb_eArgError, "Illegal size for base64 keydata");
59
+
60
+ char KeyBuffer[ASCII_SIZE];
61
+ int bytes = code64( ENCODE, KeyBuffer, ASCII_SIZE, RSTRING(szKeyData64)->ptr, BUF_64_SIZE );
62
+
63
+ // check encoded key
64
+ if ( bytes != 164) rb_raise(rb_eArgError, "Illegal size for keydata");
65
+
66
+ pSign = new Signer(RSTRING(szWMID)->ptr, RSTRING(szPwd)->ptr, "");
67
+ VALUE tdata = Data_Wrap_Struct(self, 0, signer_free, pSign);
68
+
69
+ pSign->isIgnoreKeyFile = TRUE;
70
+ pSign->Key64Flag = TRUE;
71
+
72
+ if (pSign) pSign->SetKeyFromCL( TRUE, KeyBuffer );
73
+
74
+ return tdata;
75
+ }
76
+
77
+ extern "C" VALUE signer_init(VALUE self)
78
+ {
79
+ return self;
80
+ }
81
+
82
+ extern "C" VALUE signer_sign(VALUE self, VALUE szIn)
83
+ {
84
+ VALUE ret;
85
+ ret = rb_str_new2("");
86
+
87
+ Signer *pSign;
88
+
89
+ Data_Get_Struct(self, Signer, pSign);
90
+
91
+ if(NIL_P(szIn)) rb_raise(rb_eArgError, "nil for sign");
92
+
93
+ if (pSign)
94
+ {
95
+ szptr szSign;
96
+ if (pSign->Sign(RSTRING(szIn)->ptr, szSign))
97
+ {
98
+ ret = rb_str_new2((char *)(const char *)szSign);
99
+ }
100
+ }
101
+
102
+ int err_no = pSign->ErrorCode();
103
+ if (err_no){
104
+ char err[20];
105
+ sprintf(err, "Signer error: %d", err_no);
106
+ rb_raise(rb_eStandardError, err);
107
+ }
108
+
109
+ return ret;
110
+ }
111
+
112
+ // The initialization method for this module
113
+ extern "C" void Init_wmsigner()
114
+ {
115
+ cSigner = rb_define_class("Signer", rb_cObject);
116
+ rb_define_singleton_method(cSigner, "new", (ruby_method*) &signer_new, 3);
117
+ rb_define_method(cSigner, "initialize", (ruby_method*) &signer_init, 0);
118
+ rb_define_method(cSigner, "sign", (ruby_method*) &signer_sign, 1);
119
+ }
@@ -0,0 +1,90 @@
1
+ WebMoney Transfer Root Authority
2
+ ================================
3
+ SHA1 Fingerprint: 76:7C:A8:69:09:10:F0:69:32:33:66:A9:C4:5D:78:6B:D1:37:17:16
4
+ PEM Data:
5
+ -----BEGIN CERTIFICATE-----
6
+ MIIEGTCCAwGgAwIBAgIQNHU6UsCDcLJD7Qw+0yqyRjANBgkqhkiG9w0BAQUFADBv
7
+ MRowGAYDVQQKExFXZWJNb25leSBUcmFuc2ZlcjEmMCQGA1UECxMdV2ViTW9uZXkg
8
+ Q2VydGlmaWNhdGlvbiBDZW50ZXIxKTAnBgNVBAMTIFdlYk1vbmV5IFRyYW5zZmVy
9
+ IFJvb3QgQXV0aG9yaXR5MB4XDTAxMDQwNDEzNDcwOVoXDTEwMDYwNzE5NDcxOFow
10
+ bzEaMBgGA1UEChMRV2ViTW9uZXkgVHJhbnNmZXIxJjAkBgNVBAsTHVdlYk1vbmV5
11
+ IENlcnRpZmljYXRpb24gQ2VudGVyMSkwJwYDVQQDEyBXZWJNb25leSBUcmFuc2Zl
12
+ ciBSb290IEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
13
+ AO9V0RYrJYPCOR7odiyICWNuoZj0tN9Z1mY10s+QIYGsMZCNG0meQymt5jTuhD/E
14
+ GNAHVVR9st3C92pqy2UAvQyAxMmzg5SJbuo/39YSAqx0vEtehl4QfHWHSiFStbbt
15
+ ZslHdl1jYKLwm6B88XI3OpiAoMAccntSazvim1k18lZ2bsTJeiH4s8BLP5T0Yw+R
16
+ belHaJe1DiRWChoKqoVqsDp5mH7v0cEpD78KltHo57zUuH+rzTcTeCKkO4/9CWiF
17
+ qY2FzC09wekFJ8LZ0HMlcANdLYSvmz3Ux3BvFqy8Jyt8dBhq8MRUkzZC8Cg5/lfs
18
+ ZSMHHsr1PnsIuM0OGbb1GJMCAwEAAaOBsDCBrTALBgNVHQ8EBAMCAcYwDwYDVR0T
19
+ AQH/BAUwAwEB/zAdBgNVHQ4EFgQUy51+UX4IIMT1cJShzlLHBU0/M/MwXAYDVR0f
20
+ BFUwUzBRoE+gTYZLaHR0cDovL3d3dy53bWNlcnQuY29tL0NlcnRFbnJvbGwvV2Vi
21
+ TW9uZXklMjBUcmFuc2ZlciUyMFJvb3QlMjBBdXRob3JpdHkuY3JsMBAGCSsGAQQB
22
+ gjcVAQQDAgECMA0GCSqGSIb3DQEBBQUAA4IBAQBqGyv5FVpV4MK0VYXPFqUhsyVc
23
+ SDqM+hu4U0OA0cIKHOXRV6BcbDzsNi1+6HVA2vr9PIcIVTRlGXcU95JcQe3tjbXQ
24
+ NNMpKcgL0YMW0ifMA2qu5y6nJTIu7rKCESUtsMzQUnccaXmYn0DChYuvPObb5suf
25
+ RVlsHL9Gc90eRiR8lofaDqIM82vETsQEIj1M1ifUgD5LxZuwQ8fdESZ/GHkxCosa
26
+ 9YG7WZKTMEgPSXpLmd+y24NklMi9cb+0dJce84OgMUfFAxYO71lkc0dJ5B7TJsqS
27
+ Ymwnj0x4w32Av3TiEJOQMghAJVsdPJiEzUiHMVDsAbyXQ03gZIyexFpl4QDy
28
+ -----END CERTIFICATE-----
29
+ Certificate Ingredients:
30
+ Data:
31
+ Version: 3 (0x2)
32
+ Serial Number:
33
+ 34:75:3a:52:c0:83:70:b2:43:ed:0c:3e:d3:2a:b2:46
34
+ Signature Algorithm: sha1WithRSAEncryption
35
+ Issuer: O=WebMoney Transfer, OU=WebMoney Certification Center, CN=WebMoney Transfer Root Authority
36
+ Validity
37
+ Not Before: Apr 4 13:47:09 2001 GMT
38
+ Not After : Jun 7 19:47:18 2010 GMT
39
+ Subject: O=WebMoney Transfer, OU=WebMoney Certification Center, CN=WebMoney Transfer Root Authority
40
+ Subject Public Key Info:
41
+ Public Key Algorithm: rsaEncryption
42
+ RSA Public Key: (2048 bit)
43
+ Modulus (2048 bit):
44
+ 00:ef:55:d1:16:2b:25:83:c2:39:1e:e8:76:2c:88:
45
+ 09:63:6e:a1:98:f4:b4:df:59:d6:66:35:d2:cf:90:
46
+ 21:81:ac:31:90:8d:1b:49:9e:43:29:ad:e6:34:ee:
47
+ 84:3f:c4:18:d0:07:55:54:7d:b2:dd:c2:f7:6a:6a:
48
+ cb:65:00:bd:0c:80:c4:c9:b3:83:94:89:6e:ea:3f:
49
+ df:d6:12:02:ac:74:bc:4b:5e:86:5e:10:7c:75:87:
50
+ 4a:21:52:b5:b6:ed:66:c9:47:76:5d:63:60:a2:f0:
51
+ 9b:a0:7c:f1:72:37:3a:98:80:a0:c0:1c:72:7b:52:
52
+ 6b:3b:e2:9b:59:35:f2:56:76:6e:c4:c9:7a:21:f8:
53
+ b3:c0:4b:3f:94:f4:63:0f:91:6d:e9:47:68:97:b5:
54
+ 0e:24:56:0a:1a:0a:aa:85:6a:b0:3a:79:98:7e:ef:
55
+ d1:c1:29:0f:bf:0a:96:d1:e8:e7:bc:d4:b8:7f:ab:
56
+ cd:37:13:78:22:a4:3b:8f:fd:09:68:85:a9:8d:85:
57
+ cc:2d:3d:c1:e9:05:27:c2:d9:d0:73:25:70:03:5d:
58
+ 2d:84:af:9b:3d:d4:c7:70:6f:16:ac:bc:27:2b:7c:
59
+ 74:18:6a:f0:c4:54:93:36:42:f0:28:39:fe:57:ec:
60
+ 65:23:07:1e:ca:f5:3e:7b:08:b8:cd:0e:19:b6:f5:
61
+ 18:93
62
+ Exponent: 65537 (0x10001)
63
+ X509v3 extensions:
64
+ X509v3 Key Usage:
65
+ Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
66
+ X509v3 Basic Constraints: critical
67
+ CA:TRUE
68
+ X509v3 Subject Key Identifier:
69
+ CB:9D:7E:51:7E:08:20:C4:F5:70:94:A1:CE:52:C7:05:4D:3F:33:F3
70
+ X509v3 CRL Distribution Points:
71
+ URI:http://www.wmcert.com/CertEnroll/WebMoney%20Transfer%20Root%20Authority.crl
72
+
73
+ 1.3.6.1.4.1.311.21.1:
74
+ ...
75
+ Signature Algorithm: sha1WithRSAEncryption
76
+ 6a:1b:2b:f9:15:5a:55:e0:c2:b4:55:85:cf:16:a5:21:b3:25:
77
+ 5c:48:3a:8c:fa:1b:b8:53:43:80:d1:c2:0a:1c:e5:d1:57:a0:
78
+ 5c:6c:3c:ec:36:2d:7e:e8:75:40:da:fa:fd:3c:87:08:55:34:
79
+ 65:19:77:14:f7:92:5c:41:ed:ed:8d:b5:d0:34:d3:29:29:c8:
80
+ 0b:d1:83:16:d2:27:cc:03:6a:ae:e7:2e:a7:25:32:2e:ee:b2:
81
+ 82:11:25:2d:b0:cc:d0:52:77:1c:69:79:98:9f:40:c2:85:8b:
82
+ af:3c:e6:db:e6:cb:9f:45:59:6c:1c:bf:46:73:dd:1e:46:24:
83
+ 7c:96:87:da:0e:a2:0c:f3:6b:c4:4e:c4:04:22:3d:4c:d6:27:
84
+ d4:80:3e:4b:c5:9b:b0:43:c7:dd:11:26:7f:18:79:31:0a:8b:
85
+ 1a:f5:81:bb:59:92:93:30:48:0f:49:7a:4b:99:df:b2:db:83:
86
+ 64:94:c8:bd:71:bf:b4:74:97:1e:f3:83:a0:31:47:c5:03:16:
87
+ 0e:ef:59:64:73:47:49:e4:1e:d3:26:ca:92:62:6c:27:8f:4c:
88
+ 78:c3:7d:80:bf:74:e2:10:93:90:32:08:40:25:5b:1d:3c:98:
89
+ 84:cd:48:87:31:50:ec:01:bc:97:43:4d:e0:64:8c:9e:c4:5a:
90
+ 65:e1:00:f2
data/lib/messenger.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'iconv'
2
+ require 'thread'
3
+
4
+ class Webmoney
5
+
6
+ class Messenger
7
+
8
+ def initialize(owner)
9
+ @webmoney = owner
10
+ @queue = Queue.new
11
+ @thread = Thread.new(@queue) do |q|
12
+ loop do
13
+ msg = q.pop
14
+ unless msg.nil?
15
+ begin
16
+ result = @webmoney.request(:send_message, msg)
17
+ @queue.push(msg) unless result.kind_of?(Hash)
18
+ rescue ResultError
19
+ puts "ResultError: #{@webmoney.error} #{@webmoney.errormsg}"
20
+ # Silent drop message
21
+ rescue ResponseError
22
+ puts "ResponseError: #{@webmoney.error}"
23
+ # Requeue message
24
+ @queue.push(msg)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def push(msg)
32
+ @queue.push(msg)
33
+ end
34
+
35
+ end
36
+
37
+ end
data/lib/passport.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'hpricot'
2
+
3
+ # Class for store attestat information
4
+ class Webmoney
5
+ class Passport < Wmid
6
+
7
+ # doc - Hpricot::Doc or xml-string
8
+ def initialize(doc)
9
+ doc = Hpricot.XML(doc) unless doc.kind_of?(Hpricot::Doc)
10
+ root = doc.at('/response')
11
+ if root && root['retval'] && root['retval'].to_i == 0
12
+ super(doc.at('/response/certinfo')['wmid'])
13
+ tid = doc.at('/response/certinfo/attestat/row')['tid'].to_i
14
+ recalled = doc.at('/response/certinfo/attestat/row')['recalled'].to_i
15
+ locked = doc.at('/response/certinfo/userinfo/value/row')['locked'].to_i
16
+ @attestat = ( recalled + locked > 0) ? ALIAS : tid
17
+ @created_at = Time.xmlschema(doc.at('/response/certinfo/attestat/row')['datecrt'])
18
+
19
+ # TODO more attestat fields...
20
+
21
+ # Make all instance variables readable
22
+ instance_variables.each do |n|
23
+ class << self; self; end.instance_eval {
24
+ attr_reader n.sub(/^@/, '')
25
+ }
26
+ end
27
+ end
28
+ end
29
+
30
+ # Attestate types
31
+ ALIAS = 100
32
+ FORMAL = 110
33
+ START = 120
34
+ PERSONAL = 130
35
+ PAYER = 135
36
+ CAPITALLER = 136
37
+ DEVELOPER = 140
38
+ REGISTRATOR = 150
39
+ GARANT = 170
40
+ SERVICE = 190
41
+ SERVICE2 = 200
42
+ OPERATOR = 300
43
+ end
44
+ end
data/lib/webmoney.rb ADDED
@@ -0,0 +1,237 @@
1
+ require File.dirname(__FILE__) +'/wmsigner'
2
+ require 'time'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'rubygems'
6
+ require 'iconv'
7
+ require 'builder'
8
+ require 'hpricot'
9
+
10
+ class Object
11
+ def blank?
12
+ respond_to?(:empty?) ? empty? : !self
13
+ end
14
+ end
15
+
16
+ # Main class for Webmoney lib. Instance contain info
17
+ # for Webmoney interfaces requests (wmid, key, etc).
18
+ # Implement base requests to Webmoney.
19
+ class Webmoney
20
+
21
+ # Error classes
22
+ class WebmoneyError < StandardError; end
23
+ class RequestError < WebmoneyError; end
24
+ class ResultError < WebmoneyError; end
25
+ class IncorrectWmidError < WebmoneyError; end
26
+ class CaCertificateError < WebmoneyError; end
27
+
28
+ require File.dirname(__FILE__) + '/../lib/wmid'
29
+ require File.dirname(__FILE__) + '/../lib/passport'
30
+ require File.dirname(__FILE__) + '/../lib/messenger'
31
+
32
+ attr_reader :wmid, :error, :errormsg, :last_request, :messenger
33
+
34
+ # Required options:
35
+ # :wmid (WMID)
36
+ # :password (on Classic key or Light X509 certtificate & key)
37
+ # :key (Base64 string for Classic key)
38
+ # OR TODO!
39
+ # :key (OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object) AND
40
+ # :cert OpenSSL::X509::Certificate object
41
+ # Optional:
42
+ # :ca_cert (path of a CA certification file in PEM format)
43
+ def initialize(opt = {})
44
+ @wmid = Wmid.new(opt[:wmid])
45
+
46
+ # classic or light
47
+ case opt[:key]
48
+ when String
49
+ @signer = Signer.new(@wmid, opt[:password], opt[:key])
50
+ when OpenSSL::PKey::RSA, OpenSSL::PKey::DSA
51
+ @key = opt[:key]
52
+ @cert = opt[:cert]
53
+ @password = opt[:password]
54
+ end
55
+
56
+ # ca_cert or default
57
+ @ca_cert =
58
+ if opt[:ca_cert].nil?
59
+ File.dirname(__FILE__) + '/../lib/WebMoneyCA.crt'
60
+ else
61
+ opt[:ca_cert]
62
+ end
63
+
64
+ w3s = 'https://w3s.wmtransfer.com/asp/'
65
+
66
+ @interfaces = {
67
+ 'create_invoice' => URI.parse( w3s + 'XMLInvoice.asp' ), # x1
68
+ 'create_transaction' => URI.parse( w3s + 'XMLTrans.asp' ), # x2
69
+ 'operation_history' => URI.parse( w3s + 'XMLOperations.asp' ), # x3
70
+ 'outgoing_invoices' => URI.parse( w3s + 'XMLOutInvoices.asp' ), # x4
71
+ 'finish_protect' => URI.parse( w3s + 'XMLFinishProtect.asp' ), # x5
72
+ 'send_message' => URI.parse( w3s + 'XMLSendMsg.asp'), # x6
73
+ 'check_sign' => URI.parse( w3s + 'XMLClassicAuth.asp'), # x7
74
+ 'find_wm' => URI.parse( w3s + 'XMLFindWMPurse.asp'), # x8
75
+ 'balance' => URI.parse( w3s + 'XMLPurses.asp'), # x9
76
+ 'incoming_invoices' => URI.parse( w3s + 'XMLInInvoices.asp'), # x10
77
+ 'get_passport' => URI.parse( 'https://passport.webmoney.ru/asp/XMLGetWMPassport.asp'), # x11
78
+ 'reject_protection' => URI.parse( w3s + 'XMLRejectProtect.asp'), # x13
79
+ 'transaction_moneyback' => URI.parse( w3s + 'XMLTransMoneyback.asp'), # 14
80
+ 'i_trust' => URI.parse( w3s + 'XMLTrustList.asp'), # x15
81
+ 'trust_me' => URI.parse( w3s + 'XMLTrustList2.asp'), # x15
82
+ 'trust_save' => URI.parse( w3s + 'XMLTrustSave2.asp'), # x15
83
+ 'create_purse' => URI.parse( w3s + 'XMLCreatePurse.asp'), # x16
84
+ 'bussines_level' => URI.parse( 'https://stats.wmtransfer.com/levels/XMLWMIDLevel.aspx')
85
+ }
86
+ # Iconv.new(to, from)
87
+ @ic_in = Iconv.new('UTF-8', 'CP1251')
88
+ @ic_out = Iconv.new('CP1251', 'UTF-8')
89
+ end
90
+
91
+ def classic?
92
+ ! @signer.nil?
93
+ end
94
+
95
+ # Send message through Queue and Thread
96
+ # Params - :wmid, :subj, :text
97
+ def send_message(params)
98
+ @messenger = Messenger.new(self) if @messenger.nil?
99
+ @messenger.push(params)
100
+ end
101
+
102
+ # ================================================
103
+ # Main interface function
104
+ # ================================================
105
+ def request(iface, opt ={})
106
+ reqn = reqn()
107
+ raise ArgumentError unless opt.kind_of?(Hash)
108
+ opt[:wmid] = @wmid if opt[:wmid].nil?
109
+ x = Builder::XmlMarkup.new(:indent => 1)
110
+ x.instruct!(:xml, :version=>"1.0", :encoding=>"windows-1251")
111
+ unless [:get_passport, :bussines_level].include?(iface)
112
+ x.tag!('w3s.request') do
113
+ x.wmid @wmid
114
+ case iface
115
+ when :check_sign then
116
+ plan_out = @ic_out.iconv(opt[:plan])
117
+ x.testsign do
118
+ x.wmid opt[:wmid]
119
+ x.plan { x.cdata! plan_out }
120
+ x.sign opt[:sign]
121
+ end
122
+ plan = @wmid + opt[:wmid] + plan_out + opt[:sign]
123
+ when :send_message
124
+ x.reqn reqn
125
+ msgsubj = @ic_out.iconv(opt[:subj])
126
+ msgtext = @ic_out.iconv(opt[:text])
127
+ x.message do
128
+ x.receiverwmid opt[:wmid]
129
+ x.msgsubj { x.cdata! msgsubj }
130
+ x.msgtext { x.cdata! msgtext }
131
+ end
132
+ plan = opt[:wmid] + reqn + msgtext + msgsubj
133
+ end
134
+ x.sign sign(plan) if classic?
135
+ end
136
+ else
137
+ case iface
138
+ when :bussines_level
139
+ x.tag!('WMIDLevel.request') do
140
+ x.signerwmid @wmid
141
+ x.wmid opt[:wmid]
142
+ end
143
+ when :get_passport
144
+ x.request do
145
+ x.wmid @wmid
146
+ x.passportwmid opt[:wmid]
147
+ x.params { x.dict 0; x.info 1; x.mode 0 }
148
+ x.sign sign(@wmid + opt[:wmid]) if classic?
149
+ end
150
+ end
151
+ end
152
+
153
+ # Request do!
154
+ res = https_request(iface, x.target!)
155
+
156
+ # Parse response
157
+ parse_retval(res)
158
+ doc = Hpricot.XML(res)
159
+ case iface
160
+ when :check_sign
161
+ return doc.at('//testsign/res').inner_html == 'yes' ? true : false
162
+ when :get_passport
163
+ return Passport.new(doc)
164
+ when :bussines_level
165
+ return doc.at('//level').inner_html.to_i
166
+ when :send_message
167
+ time = doc.at('//message/datecrt').inner_html
168
+ m = time.match(/(\d{4})(\d{2})(\d{2}) (\d{2}):(\d{2}):(\d{2})/)
169
+ time = Time.mktime(*m[1..6])
170
+ return {:id => doc.at('//message')['id'], :date => time}
171
+ end
172
+ end
173
+
174
+ protected
175
+
176
+ # Signing string by instance wmid's
177
+ # Return signed string
178
+ def sign(str)
179
+ @signer.sign(str) unless str.blank?
180
+ end
181
+
182
+ # Make HTTPS request, return result body if 200 OK
183
+ def https_request(iface, xml)
184
+ url = case iface
185
+ when Symbol
186
+ @interfaces[iface.to_s]
187
+ when String
188
+ URI.parse(iface)
189
+ end
190
+ http = Net::HTTP.new(url.host, url.port)
191
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
192
+ if File.file? @ca_cert
193
+ http.ca_file = @ca_cert
194
+ else
195
+ raise CaCertificateError
196
+ end
197
+ http.use_ssl = true
198
+ @last_request = xml
199
+ result = http.post( url.path, xml, "Content-Type" => "text/xml" )
200
+ case result
201
+ when Net::HTTPSuccess
202
+ # replace root tag for Hpricot
203
+ res = result.body.gsub(/(w3s\.response|WMIDLevel\.response)/,'w3s_response')
204
+ return @ic_in.iconv(res)
205
+ else
206
+ @error = result.code
207
+ @errormsg = result.body if result.class.body_permitted?()
208
+ raise RequestError
209
+ end
210
+ end
211
+
212
+ def parse_retval(response_xml)
213
+ doc = Hpricot.XML(response_xml)
214
+ retval_element = doc.at('//retval')
215
+ # Workaround for passport interface
216
+ unless retval_element.nil?
217
+ retval = retval_element.inner_html.to_i
218
+ retdesc = doc.at('//retdesc').inner_html unless doc.at('//retdesc').nil?
219
+ else
220
+ retval = doc.at('//response')['retval'].to_i
221
+ retdesc = doc.at('//response')['retdesc']
222
+ end
223
+ unless retval == 0
224
+ @error = retval
225
+ @errormsg = retdesc
226
+ raise ResultError
227
+ end
228
+ end
229
+
230
+ # Create unique Request Number based on time
231
+ # Return 16 digits string
232
+ def reqn
233
+ t = Time.now
234
+ t.strftime('%Y%m%d%H%M%S') + t.to_f.to_s.match(/\.(\d\d)/)[1]
235
+ end
236
+
237
+ end