Index: branches/fundraising/extensions/DonationInterface/tests/DonationInterfaceTest.php |
— | — | @@ -11,17 +11,223 @@ |
12 | 12 | * |
13 | 13 | * @group Fundraising |
14 | 14 | * @group Splunge |
| 15 | + * @group Gateways |
15 | 16 | * @author Katie Horn <khorn@wikimedia.org> |
16 | 17 | */ |
17 | 18 | class DonationInterfaceTest extends MediaWikiTestCase { |
18 | 19 | |
| 20 | + function testbuildRequestXML() { |
| 21 | + $gateway = new TestAdapter(); |
| 22 | + $gateway->publicCurrentTransaction( 'Test1' ); |
| 23 | + $built = $gateway->buildRequestXML(); |
| 24 | + $expected = '<?xml version="1.0"?>' . "\n"; |
| 25 | + $expected .= '<XML><REQUEST><ACTION>Donate</ACTION><ACCOUNT><MERCHANTID>128</MERCHANTID><PASSWORD>k4ftw</PASSWORD><VERSION>3.2</VERSION><RETURNURL>http://localhost/index.php/Donate-thanks/en</RETURNURL></ACCOUNT><DONATION><DONOR> </DONOR><AMOUNT>0</AMOUNT><CURRENCYCODE>USD</CURRENCYCODE><LANGUAGECODE>en</LANGUAGECODE><COUNTRYCODE>US</COUNTRYCODE></DONATION></REQUEST></XML>' . "\n"; |
| 26 | + $this->assertEquals($built, $expected, "The constructed XML for transaction type Test1 does not match our expected."); |
| 27 | + |
| 28 | + } |
| 29 | + |
| 30 | + function testParseResponseXML() { |
| 31 | + $gateway = new TestAdapter(); |
| 32 | + $returned = $gateway->do_transaction( 'Test2' ); |
| 33 | + |
| 34 | + $expected_errors = array( |
| 35 | + 128 => "Your shoe's untied...", |
| 36 | + 45 => "Low clearance!" |
| 37 | + ); |
| 38 | + |
| 39 | + $expected_data = array( |
| 40 | + 'thing' => 'stuff', |
| 41 | + 'otherthing' => 12, |
| 42 | + ); |
| 43 | + |
| 44 | + $this->assertEquals($returned['status'], true, "Status should be true at this point."); |
| 45 | + |
| 46 | + $this->assertEquals($returned['errors'], $expected_errors, "Expected errors were not found."); |
| 47 | + |
| 48 | + $this->assertEquals($returned['data'], $expected_data, "Expected data was not found."); |
| 49 | + |
| 50 | + $this->assertEquals($returned['message'], "Test2 Transaction Successful!", "Expected message was not returned."); |
| 51 | + |
| 52 | + } |
| 53 | + |
| 54 | +} |
| 55 | + |
| 56 | +$dir = dirname( __FILE__ ) . '/'; |
| 57 | +require_once( $dir . '../gateway_common/gateway.adapter.php' ); |
| 58 | + |
| 59 | +class TestAdapter extends GatewayAdapter { |
| 60 | + |
| 61 | + const gatewayname = 'Test Gateway'; |
| 62 | + const identifier = 'testgateway'; |
| 63 | + const communicationtype = 'xml'; |
| 64 | + const globalprefix = 'wgTestAdapterGateway'; |
| 65 | + |
| 66 | + function stageData(){ |
| 67 | + $this->postdata['amount'] = $this->postdata['amount'] * 1000; |
| 68 | + $this->postdata['name'] = $this->postdata['fname'] . " " . $this->postdata['lname']; |
| 69 | + } |
| 70 | + |
| 71 | + function __construct( ) { |
| 72 | + global $wgTestAdapterGatewayTestVar, $wgTestAdapterGatewayUseSyslog; |
| 73 | + $wgTestAdapterGatewayTestVar = "Hi there!"; |
| 74 | + $wgTestAdapterGatewayUseSyslog = true; |
| 75 | + $this->classlocation = __FILE__; |
| 76 | + parent::__construct(); |
| 77 | + |
| 78 | + } |
| 79 | + |
| 80 | + function defineAccountInfo(){ |
| 81 | + $this->accountInfo = array( |
| 82 | + 'MERCHANTID' => '128', |
| 83 | + 'PASSWORD' => 'k4ftw', |
| 84 | + //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
| 85 | + 'VERSION' => "3.2", |
| 86 | + ); |
| 87 | + } |
| 88 | + |
| 89 | + function defineVarMap(){ |
| 90 | + $this->var_map = array( |
| 91 | + 'DONOR' => 'name', |
| 92 | + 'AMOUNT' => 'amount', |
| 93 | + 'CURRENCYCODE' => 'currency', |
| 94 | + 'LANGUAGECODE' => 'language', |
| 95 | + 'COUNTRYCODE' => 'country', |
| 96 | + 'OID' => 'order_id', |
| 97 | + 'RETURNURL' => 'returnto', //TODO: Fund out where the returnto URL is supposed to be coming from. |
| 98 | + ); |
| 99 | + } |
| 100 | + |
| 101 | + function defineReturnValueMap(){ |
| 102 | + $this->return_value_map = array( |
| 103 | + 'AOK' => true, |
| 104 | + 'WRONG' => false, |
| 105 | + ); |
| 106 | + } |
| 107 | + |
| 108 | + function defineTransactions(){ |
| 109 | + $this->transactions = array(); |
| 110 | + |
| 111 | + $this->transactions['Test1'] = array( |
| 112 | + 'request' => array( |
| 113 | + 'REQUEST' => array( |
| 114 | + 'ACTION', |
| 115 | + 'ACCOUNT' => array( |
| 116 | + 'MERCHANTID', |
| 117 | + 'PASSWORD', |
| 118 | + 'VERSION', |
| 119 | + 'RETURNURL', |
| 120 | + ), |
| 121 | + 'DONATION' => array( |
| 122 | + 'DONOR', |
| 123 | + 'AMOUNT', |
| 124 | + 'CURRENCYCODE', |
| 125 | + 'LANGUAGECODE', |
| 126 | + 'COUNTRYCODE', |
| 127 | + //'OID', //move this to another test. It's different every time, dorkus. |
| 128 | + ) |
| 129 | + ) |
| 130 | + ), |
| 131 | + 'values' => array( |
| 132 | + 'ACTION' => 'Donate', |
| 133 | + ), |
| 134 | + ); |
| 135 | + |
| 136 | + $this->transactions['Test2'] = array( |
| 137 | + 'request' => array( |
| 138 | + 'REQUEST' => array( |
| 139 | + 'ACTION', |
| 140 | + ) |
| 141 | + ), |
| 142 | + 'values' => array( |
| 143 | + 'ACTION' => 'Donate2', |
| 144 | + ), |
| 145 | + ); |
| 146 | + self::log(print_r($this->transactions, true)); |
| 147 | + } |
| 148 | + |
19 | 149 | /** |
20 | | - * This test is deeply stupid, btw. |
| 150 | + * Take the entire response string, and strip everything we don't care about. |
| 151 | + * For instance: If it's XML, we only want correctly-formatted XML. Headers must be killed off. |
| 152 | + * return a string. |
21 | 153 | */ |
22 | | - function assertTestClassExists() { |
23 | | - $this->assertTrue( true, "WeeeooooOOOHOO!!1one1" ); |
| 154 | + function getFormattedResponse( $rawResponse ){ |
| 155 | + $xmlString = $this->stripXMLResponseHeaders($rawResponse); |
| 156 | + $displayXML = $this->formatXmlString( $xmlString ); |
| 157 | + $realXML = new DomDocument( '1.0' ); |
| 158 | + self::log( "Here is the Raw XML: " . $displayXML ); //I am apparently a huge fibber. |
| 159 | + $realXML->loadXML( trim( $xmlString ) ); |
| 160 | + return $realXML; |
24 | 161 | } |
| 162 | + |
| 163 | + /** |
| 164 | + * Parse the response to get the status. Not sure if this should return a bool, or something more... telling. |
| 165 | + */ |
| 166 | + function getResponseStatus( $response ){ |
25 | 167 | |
| 168 | + $aok = true; |
| 169 | + |
| 170 | + foreach ( $response->getElementsByTagName( 'RESULT' ) as $node ) { |
| 171 | + if ( array_key_exists( $node->nodeValue, $this->return_value_map ) && $this->return_value_map[$node->nodeValue] !== true ) { |
| 172 | + $aok = false; |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + return $aok; |
| 177 | + } |
| 178 | + |
| 179 | + /** |
| 180 | + * Parse the response to get the errors in a format we can log and otherwise deal with. |
| 181 | + * return a key/value array of codes (if they exist) and messages. |
| 182 | + */ |
| 183 | + function getResponseErrors( $response ){ |
| 184 | + $errors = array(); |
| 185 | + foreach ( $response->getElementsByTagName( 'warning' ) as $node ) { |
| 186 | + $code = ''; |
| 187 | + $message = ''; |
| 188 | + foreach ( $node->childNodes as $childnode ) { |
| 189 | + if ($childnode->nodeName === "code"){ |
| 190 | + $code = $childnode->nodeValue; |
| 191 | + } |
| 192 | + if ($childnode->nodeName === "message"){ |
| 193 | + $message = $childnode->nodeValue; |
| 194 | + } |
| 195 | + } |
| 196 | + $errors[$code] = $message; |
| 197 | + self::log( "ON NOES! ERRORS: " . print_r($errors, true) ); |
| 198 | + } |
| 199 | + return $errors; |
| 200 | + } |
| 201 | + |
| 202 | + /** |
| 203 | + * Harvest the data we need back from the gateway. |
| 204 | + * return a key/value array |
| 205 | + */ |
| 206 | + function getResponseData( $response ){ |
| 207 | + $data = array(); |
| 208 | + foreach ( $response->getElementsByTagName( 'ImportantData' ) as $node ) { |
| 209 | + foreach ( $node->childNodes as $childnode ) { |
| 210 | + if (trim($childnode->nodeValue) != ''){ |
| 211 | + $data[$childnode->nodeName] = $childnode->nodeValue; |
| 212 | + } |
| 213 | + } |
| 214 | + } |
| 215 | + self::log( "Returned Data: " . print_r($data, true)); |
| 216 | + return $data; |
| 217 | + } |
| 218 | + |
| 219 | + function processResponse( $response ) { |
| 220 | + //TODO: Stuff. |
| 221 | + } |
| 222 | + |
| 223 | + function publicCurrentTransaction( $transaction = '' ){ |
| 224 | + $this->currentTransaction( $transaction ); |
| 225 | + } |
| 226 | + |
| 227 | + function curl_transaction($data) { |
| 228 | + $data = ""; |
| 229 | + $data['result'] = 'BLAH BLAH BLAH BLAH whatever something blah blah<?xml version="1.0"?>' . "\n" . '<XML><Response><Status>AOK</Status><ImportantData><thing>stuff</thing><otherthing>12</otherthing></ImportantData><errorswarnings><warning><code>128</code><message>Your shoe\'s untied...</message></warning><warning><code>45</code><message>Low clearance!</message></warning></errorswarnings></Response></XML>'; |
| 230 | + return $data; |
| 231 | + } |
26 | 232 | } |
27 | 233 | |
28 | 234 | ?> |
Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php |
— | — | @@ -100,7 +100,12 @@ |
101 | 101 | } else { |
102 | 102 | $amount = '0.00'; |
103 | 103 | } |
| 104 | + |
| 105 | + // Get array of default account values necessary for Payflow |
| 106 | + require_once( 'includes/payflowUser.inc' ); |
104 | 107 | |
| 108 | + $payflow_data = payflowUser(); |
| 109 | + |
105 | 110 | // track the number of attempts the user has made |
106 | 111 | $numAttempt = $wgRequest->getVal( 'numAttempt', 0 ); |
107 | 112 | |
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php |
— | — | @@ -175,11 +175,11 @@ |
176 | 176 | } |
177 | 177 | } else { |
178 | 178 | // Display form for the first time |
179 | | - $adapter::log("Not posted, or not processed. Showing the form for the first time."); |
| 179 | + $this->adapter->log("Not posted, or not processed. Showing the form for the first time."); |
180 | 180 | $this->fnPayflowDisplayForm( $data, $this->errors ); |
181 | 181 | } |
182 | 182 | } else { |
183 | | - if ( !$adapter->isCache() ) { |
| 183 | + if ( !$this->adapter->isCache() ) { |
184 | 184 | // if we're not caching, there's a token mismatch |
185 | 185 | $this->errors['general']['token-mismatch'] = wfMsg( 'globalcollect_gateway-token-mismatch' ); |
186 | 186 | } |
— | — | @@ -200,13 +200,13 @@ |
201 | 201 | global $wgOut, $wgRequest; |
202 | 202 | |
203 | 203 | // save contrib tracking id early to track abondonment |
204 | | - if ( !empty($data) && ( $data[ 'numAttempt' ] == '0' && ( !$wgRequest->getText( 'utm_source_id', false ) || $wgRequest->getText( '_nocache_' ) == 'true' ) ) ) { |
205 | | - $tracked = $this->fnPayflowSaveContributionTracking( $data ); |
206 | | - if ( !$tracked ) { |
207 | | - $when = time(); |
208 | | - self::log( $data[ 'order_id' ] . ' Unable to save data to the contribution_tracking table ' . $when ); |
209 | | - } |
210 | | - } |
| 204 | +// if ( !empty($data) && ( $data[ 'numAttempt' ] == '0' && ( !$wgRequest->getText( 'utm_source_id', false ) || $wgRequest->getText( '_nocache_' ) == 'true' ) ) ) { |
| 205 | +// $tracked = $this->fnPayflowSaveContributionTracking( $data ); |
| 206 | +// if ( !$tracked ) { |
| 207 | +// $when = time(); |
| 208 | +// self::log( $data[ 'order_id' ] . ' Unable to save data to the contribution_tracking table ' . $when ); |
| 209 | +// } |
| 210 | +// } |
211 | 211 | |
212 | 212 | $form_class = $this->getFormClass(); |
213 | 213 | $form_obj = new $form_class( $data, $error ); |
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php |
— | — | @@ -4,44 +4,34 @@ |
5 | 5 | require_once( $dir . '../gateway_common/gateway.adapter.php' ); |
6 | 6 | |
7 | 7 | class GlobalCollectAdapter extends GatewayAdapter { |
8 | | - //Contains the map of THEIR var names, to OURS. |
9 | | - //I'd have gone the other way, but we'd run into 1:many pretty quick. |
10 | | - |
11 | 8 | const gatewayname = 'Global Collect'; |
12 | 9 | const identifier = 'globalcollect'; |
13 | 10 | const communicationtype = 'xml'; |
14 | 11 | const globalprefix = 'wgGlobalCollectGateway'; |
15 | 12 | |
16 | 13 | /** |
17 | | - * Anything we need to do to the data coming in, before we send it off. |
| 14 | + * stageData should alter the postdata array in all ways necessary in preparation for |
| 15 | + * communication with the gateway. |
18 | 16 | */ |
19 | 17 | function stageData(){ |
20 | | - //TODO: Make a Thing in which we do things like this. |
21 | 18 | $this->postdata['amount'] = $this->postdata['amount'] * 100; |
22 | 19 | } |
23 | 20 | |
| 21 | + |
24 | 22 | function __construct( ) { |
25 | 23 | $this->classlocation = __FILE__; |
26 | | - |
27 | 24 | parent::__construct(); |
28 | | - |
29 | | - $returnTitle = Title::newFromText( 'Donate-thanks/en' ); |
30 | | - $returnto = $returnTitle->getFullURL(); |
31 | | - |
32 | | - //this DEFINITELY needs to be defined in the parent class, and contain everything anybody might want to know. |
33 | | - $this->postdatadefaults = array( |
34 | | - 'order_id' => '112358' . rand(), |
35 | | - 'amount' => '11.38', |
36 | | - 'currency' => 'USD', |
37 | | - 'language' => 'en', |
38 | | - 'country' => 'US', |
39 | | - 'returnto' => $returnto, |
40 | | - 'user_ip' => ( self::getGlobal('Test') ) ? '12.12.12.12' : wfGetIP(), // current user's IP address |
| 25 | + } |
| 26 | + |
| 27 | + function defineAccountInfo(){ |
| 28 | + $this->accountInfo = array( |
| 29 | + 'MERCHANTID' => self::getGlobal('MerchantID'), |
| 30 | + //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
| 31 | + 'VERSION' => "1.0", |
41 | 32 | ); |
42 | | - |
43 | | - |
44 | | - ///ehh. Most of this should be broken up into functions for the sake of readibility. |
45 | | - |
| 33 | + } |
| 34 | + |
| 35 | + function defineVarMap(){ |
46 | 36 | $this->var_map = array( |
47 | 37 | 'ORDERID' => 'order_id', |
48 | 38 | 'AMOUNT' => 'amount', |
— | — | @@ -49,124 +39,73 @@ |
50 | 40 | 'LANGUAGECODE' => 'language', |
51 | 41 | 'COUNTRYCODE' => 'country', |
52 | 42 | 'MERCHANTREFERENCE' => 'order_id', |
53 | | - 'RETURNURL' => 'returnto', //I think. It might not even BE here yet. Boo-urns. |
| 43 | + 'RETURNURL' => 'returnto', //TODO: Fund out where the returnto URL is supposed to be coming from. |
54 | 44 | 'IPADDRESS' => 'user_ip', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
55 | 45 | ); |
56 | | - |
| 46 | + } |
| 47 | + |
| 48 | + function defineReturnValueMap(){ |
57 | 49 | $this->return_value_map = array( |
58 | 50 | 'OK' => true, |
59 | 51 | 'NOK' => false, |
60 | 52 | ); |
61 | | - |
62 | | - global $wgDonationInterfaceTest; //this is so the forms can see it. |
63 | | - if ( !self::getGlobal('Test') ) { |
64 | | - $this->url = self::getGlobal('URL'); |
65 | | - $wgDonationInterfaceTest = false; |
66 | | - } else { |
67 | | - $this->url = self::getGlobal('TestingURL'); |
68 | | - $wgDonationInterfaceTest = true; |
69 | | - } |
70 | | - |
71 | | - $this->accountInfo = array( |
72 | | - 'MERCHANTID' => self::getGlobal('MerchantID'), |
73 | | - //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
74 | | - 'VERSION' => "1.0", |
75 | | - ); |
76 | | - |
77 | | - //oof. This is getting a little long and unwieldy. Maybe we should build it. Or maybe that sucks. I can't tell yet. |
78 | | - /* General idea here: |
79 | | - * This bad boy will (probably) contain the structure of all possible transactions as defined by the gateway. |
80 | | - * First array key: Some way for us to id the transaction. Doesn't actually have to be the gateway's name for it, but |
81 | | - * I'm starting with that. |
82 | | - * Second array key: |
83 | | - * 'structure' contains the layout of that transaction. |
84 | | - * 'defaults' contains default values for the leaf 'values' |
85 | | - * I could put a 'type' in here, but I think we can assume that if 'structure' is multi-layer, we're XML. |
86 | | - * Array "leaves" in 'structure' will be assigned a value according to the var_map, and the posted data. |
87 | | - * There should also be a mechanism for assigning defaults, but I'm not entirely sure what that would look like quite yet... |
88 | | - * |
89 | | - */ |
90 | | - $this->transactions = array( |
91 | | - 'INSERT_ORDERWITHPAYMENT' => array( |
92 | | - 'request' => array( |
93 | | - 'REQUEST' => array( |
94 | | - 'ACTION', |
95 | | - 'META' => array( |
96 | | - 'MERCHANTID', |
97 | | -// 'IPADDRESS', |
98 | | - 'VERSION' |
| 53 | + } |
| 54 | + |
| 55 | + function defineTransactions(){ |
| 56 | + $this->transactions = array(); |
| 57 | + |
| 58 | + $this->transactions['INSERT_ORDERWITHPAYMENT'] = array( |
| 59 | + 'request' => array( |
| 60 | + 'REQUEST' => array( |
| 61 | + 'ACTION', |
| 62 | + 'META' => array( |
| 63 | + 'MERCHANTID', |
| 64 | + // 'IPADDRESS', |
| 65 | + 'VERSION' |
| 66 | + ), |
| 67 | + 'PARAMS' => array( |
| 68 | + 'ORDER' => array( |
| 69 | + 'ORDERID', |
| 70 | + 'AMOUNT', |
| 71 | + 'CURRENCYCODE', |
| 72 | + 'LANGUAGECODE', |
| 73 | + 'COUNTRYCODE', |
| 74 | + 'MERCHANTREFERENCE' |
99 | 75 | ), |
100 | | - 'PARAMS' => array( |
101 | | - 'ORDER' => array( |
102 | | - 'ORDERID', |
103 | | - 'AMOUNT', |
104 | | - 'CURRENCYCODE', |
105 | | - 'LANGUAGECODE', |
106 | | - 'COUNTRYCODE', |
107 | | - 'MERCHANTREFERENCE' |
108 | | - ), |
109 | | - 'PAYMENT' => array( |
110 | | - 'PAYMENTPRODUCTID', |
111 | | - 'AMOUNT', |
112 | | - 'CURRENCYCODE', |
113 | | - 'LANGUAGECODE', |
114 | | - 'COUNTRYCODE', |
115 | | - 'HOSTEDINDICATOR', |
116 | | - 'RETURNURL', |
117 | | - ) |
| 76 | + 'PAYMENT' => array( |
| 77 | + 'PAYMENTPRODUCTID', |
| 78 | + 'AMOUNT', |
| 79 | + 'CURRENCYCODE', |
| 80 | + 'LANGUAGECODE', |
| 81 | + 'COUNTRYCODE', |
| 82 | + 'HOSTEDINDICATOR', |
| 83 | + 'RETURNURL', |
118 | 84 | ) |
119 | 85 | ) |
120 | | - ), |
121 | | - 'values' => array( |
122 | | - 'ACTION' => 'INSERT_ORDERWITHPAYMENT', |
123 | | - 'HOSTEDINDICATOR' => '1', |
124 | | - 'PAYMENTPRODUCTID' => '3', |
125 | | - ), |
126 | | - 'result' => array( //just like the rest: This is still in flux. But the idea here is that this is the sctucture you'd scan for. |
127 | | - 'RESULT' => 'value' |
128 | | - ), |
129 | | - 'result_errors' => array( |
130 | | - 'ERROR' => array( |
131 | | - 'CODE' => 'value', //as opposed to "attribute", which would imply that it belongs to the parent... |
132 | | - 'MESSAGE' => 'value', |
133 | | - ) |
134 | | - ), |
135 | | - 'result_data' => array( |
136 | | - 'ROW' => array( |
137 | | - //uhh... presumably we'd look for some Stuff in here. |
138 | | - ) |
139 | 86 | ) |
140 | 87 | ), |
141 | | - 'TEST_CONNECTION' => array( |
142 | | - 'request' => array( |
143 | | - 'REQUEST' => array( |
144 | | - 'ACTION', |
145 | | - 'META' => array( |
146 | | - 'MERCHANTID', |
| 88 | + 'values' => array( |
| 89 | + 'ACTION' => 'INSERT_ORDERWITHPAYMENT', |
| 90 | + 'HOSTEDINDICATOR' => '1', |
| 91 | + 'PAYMENTPRODUCTID' => '3', |
| 92 | + ), |
| 93 | + ); |
| 94 | + |
| 95 | + $this->transactions['TEST_CONNECTION'] = array( |
| 96 | + 'request' => array( |
| 97 | + 'REQUEST' => array( |
| 98 | + 'ACTION', |
| 99 | + 'META' => array( |
| 100 | + 'MERCHANTID', |
147 | 101 | // 'IPADDRESS', |
148 | | - 'VERSION' |
149 | | - ), |
150 | | - 'PARAMS' => array( ) |
151 | | - ) |
152 | | - ), |
153 | | - 'values' => array( |
154 | | - 'ACTION' => 'TEST_CONNECTION' |
155 | | - ), |
156 | | - 'result' => array( //just like the rest: This is still in flux. But the idea here is that this is the sctucture you'd scan for. |
157 | | - 'RESULT' => 'value' |
158 | | - ), |
159 | | - 'result_errors' => array( |
160 | | - 'ERROR' => array( |
161 | | - 'CODE' => 'value', //as opposed to "attribute", which would imply that it belongs to the parent... |
162 | | - 'MESSAGE' => 'value', |
163 | | - ) |
164 | | - ), |
165 | | - 'result_data' => array( |
166 | | - 'ROW' => array( |
167 | | - //uhh... presumably we'd look for some Stuff in here. |
168 | | - ) |
| 102 | + 'VERSION' |
| 103 | + ), |
| 104 | + 'PARAMS' => array( ) |
169 | 105 | ) |
170 | 106 | ), |
| 107 | + 'values' => array( |
| 108 | + 'ACTION' => 'TEST_CONNECTION' |
| 109 | + ) |
171 | 110 | ); |
172 | 111 | } |
173 | 112 | |
— | — | @@ -239,5 +178,9 @@ |
240 | 179 | self::log( "Returned Data: " . print_r($data, true)); |
241 | 180 | return $data; |
242 | 181 | } |
| 182 | + |
| 183 | + function processResponse( $response ) { |
| 184 | + //TODO: Stuff. |
| 185 | + } |
243 | 186 | |
244 | 187 | } |
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php |
— | — | @@ -28,9 +28,49 @@ |
29 | 29 | function getResponseData( $response ); |
30 | 30 | |
31 | 31 | /** |
| 32 | + * Actually do... stuff. Here. |
| 33 | + * TODO: Better comment. |
| 34 | + * Process the entire response gott'd by the last four functions. |
| 35 | + */ |
| 36 | + function processResponse( $response ); |
| 37 | + |
| 38 | + /** |
32 | 39 | * Anything we need to do to the data coming in, before we send it off. |
33 | 40 | */ |
34 | 41 | function stageData(); |
| 42 | + |
| 43 | + /** |
| 44 | + * defineTransactions will define the $transactions array. |
| 45 | + * The array will contain everything we need to know about the request structure for all the transactions we care about, |
| 46 | + * for the current gateway. |
| 47 | + * First array key: Some way for us to id the transaction. Doesn't actually have to be the gateway's name for it, but I'm going with that until I have a reason not to. |
| 48 | + * Second array key: |
| 49 | + * 'request' contains the structure of that request. Leaves in the array tree will eventually be mapped to actual values of ours, |
| 50 | + * according to the precidence established in the getValue function. |
| 51 | + * 'values' contains default values for the transaction. Things that are typically not overridden should go here. |
| 52 | + */ |
| 53 | + function defineTransactions(); |
| 54 | + |
| 55 | + /** |
| 56 | + * defineVarMap needs to set up the $var_map array. |
| 57 | + * Keys = the name (or node name) value in the gateway transaction |
| 58 | + * Values = the mediawiki field name for the corresponding piece of data. |
| 59 | + */ |
| 60 | + function defineVarMap(); |
| 61 | + |
| 62 | + /** |
| 63 | + * defineAccountInfo needs to set up the $accountInfo array. |
| 64 | + * Keys = the name (or node name) value in the gateway transaction |
| 65 | + * Values = The actual values for those keys. Probably have to access a global or two. (use getGlobal()!) |
| 66 | + */ |
| 67 | + function defineAccountInfo(); |
| 68 | + |
| 69 | + /** |
| 70 | + * defineReturnValueMap sets up the $return_value_map array. |
| 71 | + * Keys = The different constants that may be contained as values in the gateway's response. |
| 72 | + * Values = what that string constant means to mediawiki. |
| 73 | + */ |
| 74 | + function defineReturnValueMap(); |
35 | 75 | } |
36 | 76 | |
37 | 77 | abstract class GatewayAdapter implements GatewayType { |
— | — | @@ -41,28 +81,66 @@ |
42 | 82 | protected $accountInfo; |
43 | 83 | protected $url; |
44 | 84 | protected $transactions; |
| 85 | + protected $return_value_map; |
45 | 86 | protected $postdata; |
46 | 87 | protected $postdatadefaults; |
47 | 88 | protected $xmlDoc; |
48 | 89 | protected $dataObj; |
49 | 90 | |
| 91 | + //ALL OF THESE need to be redefined in the children. Much voodoo depends on the accuracy of these constants. |
50 | 92 | const gatewayname = 'Donation Gateway'; |
51 | 93 | const identifier = 'donation'; |
52 | 94 | const communicationtype = 'xml'; //this needs to be either 'xml' or 'namevalue' |
53 | 95 | const globalprefix = 'wgDonationGateway'; //...for example. |
54 | 96 | |
55 | 97 | function __construct(){ |
| 98 | + |
56 | 99 | $dir = dirname( __FILE__ ) . '/'; |
57 | 100 | require_once( $dir . '../gateway_common/DonationData.php' ); |
58 | 101 | $this->dataObj = new DonationData(get_called_class()); |
59 | 102 | |
60 | 103 | $this->postdata = $this->dataObj->getData(); |
61 | | - self::log("Back in the Gateway Adapter: " . print_r($this->postdata, true)); |
62 | 104 | //TODO: Fix this a bit. |
63 | 105 | $this->posted = $this->dataObj->wasPosted(); |
| 106 | + |
| 107 | + global $wgDonationInterfaceTest; //this is so the forms can see it. |
| 108 | + //TODO: Alter the forms so they don't need the global? |
| 109 | + if ( !self::getGlobal('Test') ) { |
| 110 | + $this->url = self::getGlobal('URL'); |
| 111 | + $wgDonationInterfaceTest = false; |
| 112 | + } else { |
| 113 | + $this->url = self::getGlobal('TestingURL'); |
| 114 | + $wgDonationInterfaceTest = true; |
| 115 | + } |
| 116 | + |
| 117 | + $this->setPostDefaults(); |
| 118 | + $this->defineTransactions(); |
| 119 | + $this->defineVarMap(); |
| 120 | + $this->defineAccountInfo(); |
| 121 | + $this->defineReturnValueMap(); |
| 122 | + |
| 123 | + |
64 | 124 | $this->stageData(); |
65 | 125 | } |
66 | 126 | |
| 127 | + /** |
| 128 | + * Override this in children if you want different defaults. |
| 129 | + */ |
| 130 | + function setPostDefaults(){ |
| 131 | + $returnTitle = Title::newFromText( 'Donate-thanks/en' ); |
| 132 | + $returnto = $returnTitle->getFullURL(); |
| 133 | + |
| 134 | + $this->postdatadefaults = array( |
| 135 | + 'order_id' => '112358' . rand(), |
| 136 | + 'amount' => '11.38', |
| 137 | + 'currency' => 'USD', |
| 138 | + 'language' => 'en', |
| 139 | + 'country' => 'US', |
| 140 | + 'returnto' => $returnto, |
| 141 | + 'user_ip' => ( self::getGlobal('Test') ) ? '12.12.12.12' : wfGetIP(), // current user's IP address |
| 142 | + ); |
| 143 | + } |
| 144 | + |
67 | 145 | function checkTokens(){ |
68 | 146 | return $this->dataObj->checkTokens(); |
69 | 147 | } |
— | — | @@ -196,6 +274,8 @@ |
197 | 275 | |
198 | 276 | //if we're still okay (hey, even if we're not), get relevent dataz. |
199 | 277 | $returned['data'] = $this->getResponseData($formatted); |
| 278 | + |
| 279 | + $this->processResponse($returned); |
200 | 280 | |
201 | 281 | //TODO: Actually pull these from somewhere legit. |
202 | 282 | if ( $returned['status'] === true ) { |
— | — | @@ -306,6 +386,7 @@ |
307 | 387 | if ( $return['headers']['http_code'] != 200 ) { |
308 | 388 | $return['result'] = false; |
309 | 389 | //TODO: i18n here! |
| 390 | + //TODO: But also, fire off some kind of "No response from the gateway" thing to somebody so we know right away. |
310 | 391 | $return['message'] = 'No response from ' . self::getGatewayName() . '. Please try again later!'; |
311 | 392 | $when = time(); |
312 | 393 | self::log( $this->postdatadefaults['order_id'] . ' No response from ' . self::getGatewayName() . ': ' . curl_error( $ch ) ); |