Index: branches/fundraising/extensions/DonationInterface/donationinterface.php |
— | — | @@ -89,6 +89,17 @@ |
90 | 90 | # Unit tests |
91 | 91 | $wgHooks['UnitTestsList'][] = 'efDonationInterfaceUnitTests'; |
92 | 92 | |
| 93 | +// |
| 94 | +//// Resource modules |
| 95 | +//$wgResourceTemplate = array( |
| 96 | +// 'localBasePath' => $donationinterface_dir . 'modules', |
| 97 | +// 'remoteExtPath' => 'DonationInterface/modules', |
| 98 | +//); |
| 99 | +//$wgResourceModules['jquery.donationInterface'] = array( |
| 100 | +// 'scripts' => 'jquery.donationInterface.js', |
| 101 | +// 'dependencies' => 'jquery.json', |
| 102 | +//) + $wgResourceTemplate; |
| 103 | + |
93 | 104 | function efDonationInterfaceUnitTests( &$files ) { |
94 | 105 | $files[] = dirname( __FILE__ ) . '/tests/GatewayAdapterTest.php'; |
95 | 106 | $files[] = dirname( __FILE__ ) . '/tests/DonationDataTest.php'; |
Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.php |
— | — | @@ -174,7 +174,7 @@ |
175 | 175 | /** |
176 | 176 | * Hook to supply the page address of the payment gateway |
177 | 177 | * |
178 | | - * The user will be redirected here with supplied data with input data appended (GET). |
| 178 | + * The user will redirected here with supplied data with input data appended (GET). |
179 | 179 | * For example, if $url[$key] = index.php?title=Special:PayflowProGateway |
180 | 180 | * the result might look like this: http://www.yourdomain.com/index.php?title=Special:PayflowProGateway&amount=75.00¤cy_code=USD&payment_method=payflow |
181 | 181 | */ |
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php |
— | — | @@ -20,7 +20,7 @@ |
21 | 21 | * Holds the GlobalCollect response from a transaction |
22 | 22 | * @var array |
23 | 23 | */ |
24 | | - public $payflow_response = array(); |
| 24 | + public $payflow_response = array( ); |
25 | 25 | |
26 | 26 | /** |
27 | 27 | * A container for the form class |
— | — | @@ -34,7 +34,7 @@ |
35 | 35 | * An array of form errors |
36 | 36 | * @var array |
37 | 37 | */ |
38 | | - public $errors = array(); |
| 38 | + public $errors = array( ); |
39 | 39 | |
40 | 40 | /** |
41 | 41 | * Constructor - set up the new special page |
— | — | @@ -53,7 +53,7 @@ |
54 | 54 | */ |
55 | 55 | public function execute( $par ) { |
56 | 56 | global $wgRequest, $wgOut, $wgExtensionAssetsPath, |
57 | | - $wgPayFlowProGatewayCSSVersion; |
| 57 | + $wgPayFlowProGatewayCSSVersion; |
58 | 58 | |
59 | 59 | $wgOut->addExtensionStyle( |
60 | 60 | $wgExtensionAssetsPath . '/DonationInterface/gateway_forms/css/gateway.css?284' . |
— | — | @@ -90,9 +90,9 @@ |
91 | 91 | </script> |
92 | 92 | EOT; |
93 | 93 | $wgOut->addHeadItem( 'logolinkoverride', $js ); |
94 | | - |
| 94 | + |
95 | 95 | $this->setHeaders(); |
96 | | - |
| 96 | + |
97 | 97 | //TODO: This is short-circuiting what I really want to do here. |
98 | 98 | //so stop it. |
99 | 99 | $data = $this->adapter->getDisplayData(); |
— | — | @@ -116,45 +116,44 @@ |
117 | 117 | // allow any external validators to have their way with the data |
118 | 118 | $result = $this->adapter->do_transaction( 'INSERT_ORDERWITHPAYMENT' ); |
119 | 119 | //$result = $this->adapter->do_transaction( 'TEST_CONNECTION' ); |
120 | | - |
121 | | - if (!empty($result['errors'])){ |
122 | | - $wgOut->addHTML("<ul>"); |
123 | | - foreach ($result['errors'] as $code => $value){ |
124 | | - $wgOut->addHTML("<li>Error $code: $value"); |
| 120 | + |
| 121 | + $wgOut->addHTML( $result['message'] ); |
| 122 | + if ( !empty( $result['errors'] ) ) { |
| 123 | + $wgOut->addHTML( "<ul>" ); |
| 124 | + foreach ( $result['errors'] as $code => $value ) { |
| 125 | + $wgOut->addHTML( "<li>Error $code: $value" ); |
125 | 126 | } |
126 | | - $wgOut->addHTML("</ul>"); |
| 127 | + $wgOut->addHTML( "</ul>" ); |
127 | 128 | } |
128 | | - |
129 | | - if (!empty($result['data'])){ |
130 | | - // Create new page here with iframe. |
131 | | - $paymentFrame = Xml::openElement( 'iframe', |
132 | | - array( |
133 | | - 'id' => 'globalcollectframe', |
134 | | - 'name' => 'globalcollectframe', |
135 | | - 'width' => '680', |
136 | | - 'height' => '300', |
137 | | - 'frameborder' => '0', |
138 | | - 'style' => 'display:block;', |
139 | | - 'src' => $result['data']['FORMACTION'] |
140 | | - ) |
141 | | - ); |
142 | | - $paymentFrame .= Xml::closeElement( 'iframe' ); |
| 129 | + |
| 130 | + if ( !empty( $result['data'] ) ) { |
| 131 | + $wgOut->addHTML( "<ul>" ); |
| 132 | + foreach ( $result['data'] as $key => $value ) { |
| 133 | + $wgOut->addHTML( "<li>$key: $value" ); |
| 134 | + } |
| 135 | + $wgOut->addHTML( "</ul>" ); |
143 | 136 | |
144 | | - $wgOut->addHTML( $paymentFrame ); |
145 | | - } |
146 | | - |
147 | | - /* |
148 | | - $wgOut->addHTML($result['message']); |
149 | | - if (!empty($result['data'])){ |
150 | | - $wgOut->addHTML("<ul>"); |
151 | | - foreach ($result['data'] as $key => $value){ |
152 | | - $wgOut->addHTML("<li>$key: $value"); |
| 137 | + if (array_key_exists('FORMACTION', $result['data'])){ |
| 138 | + $paymentFrame = Xml::openElement( 'iframe', |
| 139 | + array( |
| 140 | + 'id' => 'globalcollectframe', |
| 141 | + 'name' => 'globalcollectframe', |
| 142 | + 'width' => '680', |
| 143 | + 'height' => '300', |
| 144 | + 'frameborder' => '0', |
| 145 | + 'style' => 'display:block;', |
| 146 | + 'src' => $result['data']['FORMACTION'] |
| 147 | + ) |
| 148 | + ); |
| 149 | + $paymentFrame .= Xml::closeElement( 'iframe' ); |
| 150 | + |
| 151 | + $wgOut->addHTML( $paymentFrame ); |
| 152 | + |
153 | 153 | } |
154 | | - $wgOut->addHTML("</ul>"); |
155 | 154 | } |
156 | | - */ |
157 | 155 | |
158 | 156 | |
| 157 | + |
159 | 158 | // self::log( $data[ 'order_id' ] . " Preparing to query MaxMind" ); |
160 | 159 | // wfRunHooks( 'PayflowGatewayValidate', array( &$this, &$data ) ); |
161 | 160 | // self::log( $data[ 'order_id' ] . ' Finished querying Maxmind' ); |
— | — | @@ -348,7 +347,7 @@ |
349 | 348 | */ |
350 | 349 | private function fnPayflowGetResults( $data, $result ) { |
351 | 350 | // prepare NVP response for sorting and outputting |
352 | | - $responseArray = array(); |
| 351 | + $responseArray = array( ); |
353 | 352 | |
354 | 353 | /** |
355 | 354 | * The result response string looks like: |
— | — | @@ -474,7 +473,7 @@ |
475 | 474 | public function prepareStompTransaction( $data, $responseArray, $responseMsg ) { |
476 | 475 | $countries = $this->getCountries(); |
477 | 476 | |
478 | | - $transaction = array(); |
| 477 | + $transaction = array( ); |
479 | 478 | |
480 | 479 | // include response message |
481 | 480 | $transaction['response'] = $responseMsg; |
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php |
— | — | @@ -12,6 +12,25 @@ |
13 | 13 | */ |
14 | 14 | function stageData() { |
15 | 15 | $this->postdata['amount'] = $this->postdata['amount'] * 100; |
| 16 | + |
| 17 | + switch ( $this->postdata['card_type'] ) { |
| 18 | + case 'visa': |
| 19 | + $this->postdata['card_type'] = 1; |
| 20 | + break; |
| 21 | + case 'mastercard': |
| 22 | + $this->postdata['card_type'] = 3; |
| 23 | + break; |
| 24 | + case 'american': |
| 25 | + $this->postdata['card_type'] = 2; |
| 26 | + break; |
| 27 | + case 'discover': |
| 28 | + $this->postdata['card_type'] = 128; |
| 29 | + break; |
| 30 | + } |
| 31 | + |
| 32 | + $this->postdata['expiry'] = $this->postdata['expiration']; //. ($this->postdata['year'] % 100); |
| 33 | + $this->postdata['card_num'] = str_replace(' ', '', $this->postdata['card_num']); |
| 34 | + |
16 | 35 | } |
17 | 36 | |
18 | 37 | function defineAccountInfo() { |
— | — | @@ -32,6 +51,17 @@ |
33 | 52 | 'MERCHANTREFERENCE' => 'order_id', |
34 | 53 | 'RETURNURL' => 'returnto', //TODO: Fund out where the returnto URL is supposed to be coming from. |
35 | 54 | 'IPADDRESS' => 'user_ip', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
| 55 | + 'PAYMENTPRODUCTID' => 'card_type', |
| 56 | + 'CVV' => 'cvv', |
| 57 | + 'EXPIRYDATE' => 'expiry', |
| 58 | + 'CREDITCARDNUMBER' => 'card_num', |
| 59 | + 'FIRSTNAME' => 'fname', |
| 60 | + 'SURNAME' => 'lname', |
| 61 | + 'STREET' => 'street', |
| 62 | + 'CITY' => 'city', |
| 63 | + 'STATE' => 'state', |
| 64 | + 'ZIP' => 'zip', |
| 65 | + 'EMAIL' => 'email', |
36 | 66 | ); |
37 | 67 | } |
38 | 68 | |
— | — | @@ -71,14 +101,23 @@ |
72 | 102 | 'COUNTRYCODE', |
73 | 103 | 'HOSTEDINDICATOR', |
74 | 104 | 'RETURNURL', |
| 105 | + 'CVV', |
| 106 | + 'EXPIRYDATE', |
| 107 | + 'CREDITCARDNUMBER', |
| 108 | + 'FIRSTNAME', |
| 109 | + 'SURNAME', |
| 110 | + 'STREET', |
| 111 | + 'CITY', |
| 112 | + 'STATE', |
| 113 | + 'ZIP', |
| 114 | + 'EMAIL', |
75 | 115 | ) |
76 | 116 | ) |
77 | 117 | ) |
78 | 118 | ), |
79 | 119 | 'values' => array( |
80 | 120 | 'ACTION' => 'INSERT_ORDERWITHPAYMENT', |
81 | | - 'HOSTEDINDICATOR' => '1', |
82 | | - 'PAYMENTPRODUCTID' => '3', |
| 121 | + 'HOSTEDINDICATOR' => '1' |
83 | 122 | ), |
84 | 123 | ); |
85 | 124 | |
— | — | @@ -165,6 +204,24 @@ |
166 | 205 | } |
167 | 206 | } |
168 | 207 | } |
| 208 | + |
| 209 | + foreach ( $response->getElementsByTagName( 'ORDER' ) as $node ) { |
| 210 | + foreach ( $node->childNodes as $childnode ) { |
| 211 | + if ( trim( $childnode->nodeValue ) != '' ) { |
| 212 | + $data['RequestOrder-' . $childnode->nodeName] = $childnode->nodeValue; |
| 213 | + } |
| 214 | + } |
| 215 | + } |
| 216 | + |
| 217 | + foreach ( $response->getElementsByTagName( 'PAYMENT' ) as $node ) { |
| 218 | + foreach ( $node->childNodes as $childnode ) { |
| 219 | + if ( trim( $childnode->nodeValue ) != '' ) { |
| 220 | + $data['RequestPayment-' . $childnode->nodeName] = $childnode->nodeValue; |
| 221 | + } |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + |
169 | 226 | self::log( "Returned Data: " . print_r( $data, true ) ); |
170 | 227 | return $data; |
171 | 228 | } |
Index: branches/fundraising/extensions/DonationInterface/modules/jquery.donationInterface.js |
— | — | @@ -0,0 +1,214 @@ |
| 2 | +/** |
| 3 | + * Turns any form with the bare minimum "appropriate" fields into a form that |
| 4 | + * can get a donor to a gateway with no interstitial page. |
| 5 | + * To use: |
| 6 | + * *) Install the ContributionTracking Extension. |
| 7 | + * *) Include this module on a page. |
| 8 | + * *) On that page, create a form that contains (at least) the fields |
| 9 | + * required by ApiContributionTracking. |
| 10 | + * *) Make sure that form's submit button has a unique ID. |
| 11 | + * *) Assign that button the class of "ajax_me". |
| 12 | + * |
| 13 | + * @author Katie Horn <khorn@wikimedia.org> |
| 14 | + */ |
| 15 | + |
| 16 | +( function( $ ) { |
| 17 | + |
| 18 | + /** |
| 19 | + * Binds the onclick function to everything with a class of "ajax_me". |
| 20 | + */ |
| 21 | + $.bindAjaxControls = function(){ |
| 22 | + $(".ajax_me:disabled").removeAttr("disabled"); |
| 23 | + $(".ajax_me").click(function() { |
| 24 | + this.disabled = true; |
| 25 | + $.goAjax(this.id); |
| 26 | + return false; //prevent regular form submission. |
| 27 | + //TODO: Think about the button disabling and enabling. |
| 28 | + //TODO: also think about a barber pole. That would go here. |
| 29 | + }); |
| 30 | + //$("form") |
| 31 | + } |
| 32 | + |
| 33 | + /** |
| 34 | + * Turns the first parent form from the passing object, to an object we can |
| 35 | + * pass to the API. |
| 36 | + * Takes the button ID in string form. |
| 37 | + */ |
| 38 | + $.prepareXML = function(buttonID){ |
| 39 | + buttonID = "#" + buttonID; |
| 40 | + var form = $(buttonID).parents("form:first"); |
| 41 | + var xmlnode = $("#xml_structure"); |
| 42 | + var xml = $("#xml_structure").html(); |
| 43 | + |
| 44 | + delete form.attr( 'action' ); |
| 45 | + delete form.attr( 'method' ); |
| 46 | + |
| 47 | + |
| 48 | + //window.alert(xml); |
| 49 | + |
| 50 | + //xmlnode.find("merchantid").html("NEW VALUE"); |
| 51 | + //window.alert( xmlnode.find("merchantid").html() ); |
| 52 | + |
| 53 | + var serializedForm = form.serializeArray(); |
| 54 | + var sendData = $.stageData(serializedForm); |
| 55 | + |
| 56 | + //TODO: Yeah, this works, but... grow up. |
| 57 | +// for (key in sendData){ |
| 58 | +// if(xml.indexOf("@" + key) > 0){ |
| 59 | +// xml = xml.replace("@" + key, sendData[key]); |
| 60 | +// //finalObj[serializedForm[key]['name']] = serializedForm[key]['value']; |
| 61 | +// } |
| 62 | +// } |
| 63 | + |
| 64 | + //Wow. The next business works. Crizzy. |
| 65 | + |
| 66 | + $.each(xmlnode.find("order").children() , function (index) { |
| 67 | + var keyname = $(this).text().replace("@", ""); |
| 68 | + if (sendData[keyname]){ |
| 69 | + $(this).html(sendData[keyname]); |
| 70 | + } else { |
| 71 | + $(this).remove(); |
| 72 | + } |
| 73 | + }); |
| 74 | + $.each(xmlnode.find("payment").children() , function (index) { |
| 75 | + var keyname = $(this).text().replace("@", ""); |
| 76 | + if (sendData[keyname]){ |
| 77 | + $(this).html(sendData[keyname]); |
| 78 | + } else { |
| 79 | + $(this).remove(); |
| 80 | + } |
| 81 | + }); |
| 82 | + |
| 83 | + |
| 84 | + //xml = $("#xml_structure").find("request").html(); |
| 85 | + xml = $("#xml_structure").html(); |
| 86 | + window.alert(xml); |
| 87 | + return xml; |
| 88 | + } |
| 89 | + |
| 90 | + $.stageData = function(serializedForm) { |
| 91 | + var finalObj = {}; |
| 92 | + |
| 93 | + for (key in serializedForm){ |
| 94 | + if(serializedForm[key]['value'] != ""){ |
| 95 | + finalObj[serializedForm[key]['name']] = serializedForm[key]['value']; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + if (finalObj['emailAdd']){ |
| 100 | + finalObj['email'] = finalObj['emailAdd']; |
| 101 | + delete finalObj['emailAdd']; |
| 102 | + } |
| 103 | + |
| 104 | + finalObj['amount'] = finalObj['amount'] * 100; |
| 105 | + //do the rest of the staging here. |
| 106 | + |
| 107 | + $.debugPostObjectWithAlert(finalObj); |
| 108 | + |
| 109 | + return finalObj; |
| 110 | + } |
| 111 | + |
| 112 | + $(document).ajaxError(function(event, request, settings, thrown){ |
| 113 | + var display = ''; |
| 114 | + for (key in event){ |
| 115 | + display += "event " + key + " : " + event[key] + "\r\n"; |
| 116 | + } |
| 117 | + for (key in event['data']){ |
| 118 | + display += "event data " + key + " : " + event[key] + "\r\n"; |
| 119 | + } |
| 120 | + for (key in request){ |
| 121 | + display += "request " + key + " : " + event[key] + "\r\n"; |
| 122 | + } |
| 123 | + for (key in settings){ |
| 124 | + display += "settings " + key + " : " + event[key] + "\r\n"; |
| 125 | + } |
| 126 | + for (key in thrown){ |
| 127 | + display += "thrown " + key + " : " + event[key] + "\r\n"; |
| 128 | + } |
| 129 | + window.alert("Ajax Error!\r\n" + display); |
| 130 | + }); |
| 131 | + |
| 132 | + $.makeAndPostForm = function (postData){ |
| 133 | + if ($('#hideyform').length){ |
| 134 | + $('#hideyform').empty(); //just in case something is already hiding in the hideyform. |
| 135 | + } else { |
| 136 | + $('<div id="hideyform"></div>').appendTo('body'); |
| 137 | + } |
| 138 | + $('<form id="immediate_repost" action="https://ps.gcsip.nl/wdl/wdl" method="POST"></form>').appendTo('#hideyform'); |
| 139 | + $('<input type="hidden" id="xml" name="xml" value="' + postData +'">').appendTo('#immediate_repost'); |
| 140 | + $('#immediate_repost').submit(); |
| 141 | + window.alert("Form Submitted! Go look..."); |
| 142 | + } |
| 143 | + |
| 144 | + |
| 145 | + /** |
| 146 | + * Sends the formatted ajax request to the API, turns the result into a |
| 147 | + * hidden form, and immediately posts that form on return. |
| 148 | + * Takes the button ID in string form. |
| 149 | + */ |
| 150 | + $.goAjax = function(buttonID) { |
| 151 | + |
| 152 | + var postData = $.prepareXML(buttonID); |
| 153 | + //postData.action = "contributiontracking"; |
| 154 | + $.makeAndPostForm(postData); |
| 155 | + return false; |
| 156 | + |
| 157 | + |
| 158 | + var processAjaxReturn = function(data, status){ |
| 159 | + //TODO: Improve the language of the success and error dialogs. |
| 160 | + |
| 161 | + window.alert("Return! " + data); |
| 162 | + |
| 163 | + if(status != "success"){ |
| 164 | + window.alert("Status: " + status); |
| 165 | + $(buttonID).removeAttr("disabled"); |
| 166 | + $(".ajax_me:disabled").removeAttr("disabled"); |
| 167 | + return; |
| 168 | + } |
| 169 | + |
| 170 | + if(data["error"]){ |
| 171 | + //TODO: localization. And i18n. And stuff. |
| 172 | + window.alert("The following error has occurred:\r\n" + data["error"]["info"]); |
| 173 | + $(buttonID).removeAttr("disabled"); |
| 174 | + $(".ajax_me:disabled").removeAttr("disabled"); |
| 175 | + return; |
| 176 | + } |
| 177 | + |
| 178 | + if ($('#hideyform').length){ |
| 179 | + $('#hideyform').empty(); //just in case something is already hiding in the hideyform. |
| 180 | + } else { |
| 181 | + $('<div id="hideyform"></div>').appendTo('body'); |
| 182 | + } |
| 183 | + $('<form id="immediate_repost" action="' + data["returns"]["action"]["url"] + '"></form>').appendTo('#hideyform'); |
| 184 | + for (key in data["returns"]["fields"]) { |
| 185 | + $('<input type="hidden" id="' + key +'" name="' + key +'" value="' + data["returns"]["fields"][key] +'">').appendTo('#immediate_repost'); |
| 186 | + } |
| 187 | + $('#immediate_repost').submit(); |
| 188 | + |
| 189 | + } |
| 190 | + |
| 191 | +// $.post( |
| 192 | +// //mw.config.get('wgScriptPath') + '/api.php', |
| 193 | +// 'https://ps.gcsip.nl/wdl/wdl', |
| 194 | +// //'http://ps.gcsip.nl/wdl/wdl', |
| 195 | +// //'http://www.katiehorn.com/nonsense/', |
| 196 | +// postData, |
| 197 | +// processAjaxReturn, |
| 198 | +// 'xml'); |
| 199 | + } |
| 200 | + |
| 201 | + /** |
| 202 | + * Just for easy debugging. Should not actually be called anywhere. |
| 203 | + * TODO: Take this out when we know we're done here. |
| 204 | + */ |
| 205 | + $.debugPostObjectWithAlert = function(object){ |
| 206 | + var contents = ""; |
| 207 | + for (key in object){ |
| 208 | + contents += key + " = " + object[key] + "\r\n"; |
| 209 | + } |
| 210 | + window.alert(contents); |
| 211 | + } |
| 212 | + |
| 213 | +} )( jQuery ); |
| 214 | + |
| 215 | +$.bindAjaxControls(); |
\ No newline at end of file |
Property changes on: branches/fundraising/extensions/DonationInterface/modules/jquery.donationInterface.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 216 | + native |
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php |
— | — | @@ -164,7 +164,7 @@ |
165 | 165 | return $gotten[$globalname]; |
166 | 166 | } |
167 | 167 | |
168 | | - function getValue( $gateway_field_name ) { |
| 168 | + function getValue( $gateway_field_name, $token = false ) { |
169 | 169 | if ( empty( $this->transactions ) ) { |
170 | 170 | //TODO: These dies should all just throw fatal errors instead. |
171 | 171 | die( 'Transactions structure is empty! Aborting.' ); |
— | — | @@ -190,6 +190,9 @@ |
191 | 191 | |
192 | 192 | //If there's a value in the post data (name-translated by the var_map), use that. |
193 | 193 | if ( array_key_exists( $gateway_field_name, $this->var_map ) ) { |
| 194 | + if ($token === true){ //we just want the field name to use, so short-circuit all that mess. |
| 195 | + return '@' . $this->var_map[$gateway_field_name]; |
| 196 | + } |
194 | 197 | if ( array_key_exists( $this->var_map[$gateway_field_name], $this->postdata ) && |
195 | 198 | $this->postdata[$this->var_map[$gateway_field_name]] !== '' ) { |
196 | 199 | //if it was sent, use that. |
— | — | @@ -217,19 +220,19 @@ |
218 | 221 | return $this->xmlDoc->saveXML(); |
219 | 222 | } |
220 | 223 | |
221 | | - function buildTransactionNodes( $structure, &$node ) { |
| 224 | + function buildTransactionNodes( $structure, &$node, $js = false ) { |
222 | 225 | $transaction = $this->currentTransaction(); |
223 | 226 | |
224 | 227 | if ( !is_array( $structure ) ) { //this is a weird case that shouldn't ever happen. I'm just being... thorough. But, yeah: It's like... the base-1 case. |
225 | | - $this->appendNodeIfValue( $structure, $node ); |
| 228 | + $this->appendNodeIfValue( $structure, $node, $js ); |
226 | 229 | } else { |
227 | 230 | foreach ( $structure as $key => $value ) { |
228 | 231 | if ( !is_array( $value ) ) { |
229 | 232 | //do not use $key. $key is meaningless in this case. |
230 | | - $this->appendNodeIfValue( $value, $node ); |
| 233 | + $this->appendNodeIfValue( $value, $node, $js ); |
231 | 234 | } else { |
232 | 235 | $keynode = $this->xmlDoc->createElement( $key ); |
233 | | - $this->buildTransactionNodes( $value, $keynode ); |
| 236 | + $this->buildTransactionNodes( $value, $keynode, $js ); |
234 | 237 | $node->appendChild( $keynode ); |
235 | 238 | } |
236 | 239 | } |
— | — | @@ -237,30 +240,55 @@ |
238 | 241 | //not actually returning anything. It's all side-effects. Because I suck like that. |
239 | 242 | } |
240 | 243 | |
241 | | - function appendNodeIfValue( $value, &$node ) { |
242 | | - $nodevalue = $this->getValue( $value ); |
| 244 | + function appendNodeIfValue( $value, &$node, $js = false ) { |
| 245 | + $nodevalue = $this->getValue( $value, $js ); |
243 | 246 | if ( $nodevalue !== '' && $nodevalue !== false ) { |
244 | 247 | $temp = $this->xmlDoc->createElement( $value, $nodevalue ); |
245 | 248 | $node->appendChild( $temp ); |
246 | 249 | } |
247 | 250 | } |
| 251 | + |
| 252 | + //TODO: You can actually take this out if we never ever want to use ajax for a gateway. |
| 253 | + function buildTransactionFormat($transaction){ |
| 254 | + $this->currentTransaction( $transaction ); |
| 255 | + $this->xmlDoc = new DomDocument( '1.0' ); |
| 256 | + $node = $this->xmlDoc->createElement( 'XML' ); |
248 | 257 | |
| 258 | + $structure = $this->transactions[$this->currentTransaction()]['request']; |
| 259 | + |
| 260 | + $this->buildTransactionNodes( $structure, $node, true ); |
| 261 | + $this->xmlDoc->appendChild( $node ); |
| 262 | + $xml = $this->xmlDoc->saveXML(); |
| 263 | + $xmlStart = strpos($xml, "<XML>"); |
| 264 | + self::log("XML START" . $xmlStart); |
| 265 | + $xml = substr( $xml, $xmlStart ); |
| 266 | + self::log("XML stubby thing..." . $xml); |
| 267 | + |
| 268 | + return $xml; |
| 269 | + } |
| 270 | + |
249 | 271 | function do_transaction( $transaction ) { |
250 | 272 | $this->currentTransaction( $transaction ); |
251 | 273 | //update the contribution tracking data |
252 | 274 | $this->dataObj->updateContributionTracking( defined( 'OWA' ) ); |
253 | 275 | if ( $this->getCommunicationType() === 'xml' ) { |
| 276 | + $this->getStopwatch(__FUNCTION__); |
254 | 277 | $xml = $this->buildRequestXML(); |
| 278 | + $this->saveCommunicationStats("-BuildingRequestXML"); |
| 279 | + $this->getStopwatch(__FUNCTION__, true); |
255 | 280 | $returned = $this->curl_transaction( $xml ); |
| 281 | + $this->saveCommunicationStats(); |
256 | 282 | //put the response in a universal form, and return it. |
257 | 283 | } |
258 | 284 | |
259 | 285 | if ( $this->getCommunicationType() === 'namevalue' ) { |
260 | 286 | $namevalue = $this->postdata; |
| 287 | + $this->getStopwatch(__FUNCTION__); |
261 | 288 | $returned = $this->curl_transaction( $namevalue ); |
| 289 | + $this->saveCommunicationStats(); |
262 | 290 | //put the response in a universal form, and return it. |
263 | 291 | } |
264 | | - |
| 292 | + |
265 | 293 | self::log( "RETURNED FROM CURL:" . print_r( $returned, true ) ); |
266 | 294 | if ( $returned['result'] === false ) { //couldn't make contact. Bail. |
267 | 295 | return $returned; |
— | — | @@ -485,5 +513,33 @@ |
486 | 514 | $c = get_called_class(); |
487 | 515 | return $c::IDENTIFIER; |
488 | 516 | } |
| 517 | + |
| 518 | + public function getStopwatch($string, $reset = false){ |
| 519 | + static $start = null; |
| 520 | + $now = microtime(true); |
489 | 521 | |
| 522 | + if ($start == null || $reset === true){ |
| 523 | + $start = $now; |
| 524 | + } |
| 525 | + $clock = round($now - $start, 4); |
| 526 | + self::log("\nClock at $string: $clock ($now)"); |
| 527 | + return $clock; |
| 528 | + } |
| 529 | + |
| 530 | + function saveCommunicationStats( $additional = '' ) { //easier than looking at logs... |
| 531 | + $params = array(); |
| 532 | + if (self::getGlobal('SaveCommStats')){ //TODO: I should do this for real at some point. |
| 533 | + $db = ContributionTrackingProcessor::contributionTrackingConnection(); |
| 534 | + $params['contribution_id'] = $this->dataObj->getVal( 'contribution_tracking_id' ); |
| 535 | + $params['ts'] = $db->timestamp(); |
| 536 | + $params['duration'] = $this->getStopwatch(__FUNCTION__); |
| 537 | + $params['gateway'] = self::getGatewayName() . $additional; |
| 538 | + |
| 539 | + //can we check to see if the table exists? Bah, I should almost certianly do this Fer Reals. |
| 540 | + |
| 541 | + $db->insert( 'communication_stats', $params ); |
| 542 | + } |
| 543 | + |
| 544 | + } |
| 545 | + |
490 | 546 | } |
Index: branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php |
— | — | @@ -151,7 +151,7 @@ |
152 | 152 | 'size' => $wgRequest->getText( 'size' ), |
153 | 153 | 'premium_language' => $wgRequest->getText( 'premium_language', "en" ), |
154 | 154 | 'card_num' => str_replace( ' ', '', $wgRequest->getText( 'card_num' ) ), |
155 | | - 'card_type' => $wgRequest->getText( 'card' ), |
| 155 | + 'card_type' => $wgRequest->getText( 'card_type' ), |
156 | 156 | 'expiration' => $wgRequest->getText( 'mos' ) . substr( $wgRequest->getText( 'year' ), 2, 2 ), |
157 | 157 | 'cvv' => $wgRequest->getText( 'cvv' ), |
158 | 158 | 'currency' => $wgRequest->getText( 'currency_code' ), |