r98398 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98397‎ | r98398 | r98399 >
Date:02:03, 29 September 2011
Author:kaldari
Status:ok (Comments)
Tags:fundraising 
Comment:
beginnings of donation API - also had to do a few updates to DonationData.php to handle the API stuff
Modified paths:
  • /branches/fundraising/extensions/DonationInterface/donationinterface.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/donation.api.php (added) (history)
  • /branches/fundraising/extensions/DonationInterface/payflowpro_gateway/api_payflowpro_gateway.php (modified) (history)

Diff [purge]

Index: branches/fundraising/extensions/DonationInterface/donationinterface.php
@@ -59,6 +59,7 @@
6060 $wgAutoloadClasses['DonationData'] = $donationinterface_dir . 'gateway_common/DonationData.php';
6161 $wgAutoloadClasses['GatewayAdapter'] = $donationinterface_dir . 'gateway_common/gateway.adapter.php';
6262 $wgAutoloadClasses['GatewayForm'] = $donationinterface_dir . 'gateway_common/GatewayForm.php';
 63+$wgAutoloadClasses['DonationApi'] = $donationinterface_dir . 'gateway_common/donation.api.php';
6364
6465 //THE GATEWAYS WILL RESET THIS when they are instantiated. You can override it, but it won't stick around that way.
6566 $wgDonationInterfaceTest = false;
@@ -98,6 +99,8 @@
99100 # Unit tests
100101 $wgHooks['UnitTestsList'][] = 'efDonationInterfaceUnitTests';
101102
 103+// enable the API
 104+$wgAPIModules['donate'] = 'DonationApi';
102105
103106 // Resource modules
104107 $wgResourceTemplate = array(
Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/api_payflowpro_gateway.php
@@ -1,6 +1,7 @@
22 <?php
33 /**
44 * PayflowPro Gateway API extension
 5+ * Call with api.php?action=pfp
56 */
67
78 class ApiPayflowProGateway extends ApiBase {
Index: branches/fundraising/extensions/DonationInterface/gateway_common/donation.api.php
@@ -0,0 +1,57 @@
 2+<?php
 3+/**
 4+ * Generic Donation API
 5+ * This API should be able to accept donation submissions for any gateway or payment type
 6+ * Call with api.php?action=donate
 7+ */
 8+class DonationApi extends ApiBase {
 9+ public function execute() {
 10+ global $wgRequest, $wgParser;
 11+
 12+ $params = $this->extractRequestParams();
 13+
 14+ $ddObj = new DonationData( 'DonationApi', false, $params );
 15+
 16+ $normalizedData = $ddObj->getData();
 17+
 18+ // Some test output
 19+ $this->getResult()->addValue( 'data', 'gateway', $normalizedData['gateway'] );
 20+ $this->getResult()->addValue( 'data', 'amount', $normalizedData['amount'] );
 21+ }
 22+
 23+ public function getAllowedParams() {
 24+ return array(
 25+ 'gateway' => array(
 26+ ApiBase::PARAM_TYPE => 'string',
 27+ ApiBase::PARAM_REQUIRED => true,
 28+ ),
 29+ 'amount' => array(
 30+ ApiBase::PARAM_TYPE => 'string',
 31+ ),
 32+ );
 33+ }
 34+
 35+ public function getParamDescription() {
 36+ return array(
 37+ 'gateway' => 'Which payment gateway to use - payflowpro, globalcollect, etc.',
 38+ 'amount' => 'The amount donated',
 39+ );
 40+ }
 41+
 42+ public function getDescription() {
 43+ return array(
 44+ 'This API allow you to submit a donation to the Wikimedia Foundation using a',
 45+ 'variety of payment processors.',
 46+ );
 47+ }
 48+
 49+ public function getExamples() {
 50+ return array(
 51+ 'api.php?action=donate&gateway=payflowpro&amount=2.00',
 52+ );
 53+ }
 54+
 55+ public function getVersion() {
 56+ return __CLASS__ . ': $Id: DonationApi.php 1.0 kaldari $';
 57+ }
 58+}
Index: branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php
@@ -10,20 +10,20 @@
1111 protected $normalized = array( );
1212 public $boss;
1313
14 - function __construct( $owning_class, $test = false, $testdata = false ) {
 14+ function __construct( $owning_class, $test = false, $data = false ) {
1515 //TODO: Actually think about this bit.
1616 // ...and keep in mind we can re-populate if it's a test or whatever. (But that may not be a good idea either)
1717 //maybe we should just explicitly pass in where we get the data from. (Test, post, API...)
1818 $this->boss = $owning_class;
19 - $this->populateData( $test, $testdata );
 19+ $this->populateData( $test, $data );
2020 }
2121
22 - function populateData( $test = false, $testdata = false ) {
 22+ function populateData( $test = false, $data = false ) {
2323 $this->normalized = array( );
24 - //TODO: Uh, the API should probably be able to get in this far, too... and have its own populate function.
25 - //Maybe check for the boss class...
2624 if ( $test ) {
27 - $this->populateData_Test( $testdata );
 25+ $this->populateData_Test( $data );
 26+ } else if ( $this->boss == 'DonationApi' ) {
 27+ $this->populateData_Api( $data );
2828 } else {
2929 $this->populateData_Form();
3030 }
@@ -152,7 +152,7 @@
153153 'currency' => $wgRequest->getText( 'currency_code' ),
154154 'payment_method' => $wgRequest->getText( 'payment_method' ),
155155 'order_id' => $wgRequest->getText( 'order_id', null ), //as far as I know, this won't actually ever pull anything back.
156 - 'i_order_id' => $wgRequest->getText( 'i_order_id', null ),
 156+ 'i_order_id' => $wgRequest->getText( 'i_order_id', null ), //internal id for each contribution attempt
157157 'numAttempt' => $wgRequest->getVal( 'numAttempt', 0 ),
158158 'referrer' => ( $wgRequest->getVal( 'referrer' ) ) ? $wgRequest->getVal( 'referrer' ) : $wgRequest->getHeader( 'referer' ),
159159 'utm_source' => self::getUtmSource(), //TODO: yes. That.
@@ -177,6 +177,66 @@
178178 $this->setVal( 'posted', false );
179179 }
180180 }
 181+
 182+ function populateData_Api( $data ) {
 183+ global $wgRequest;
 184+ $this->normalized = array(
 185+ // Do we need 'posted' here?
 186+ 'amount' => $data['amount'],
 187+ 'amountGiven' => $data['amountGiven'],
 188+ 'amountOther' => $data['amountOther'],
 189+ 'email' => $data['email'],
 190+ 'fname' => $data['fname'],
 191+ 'mname' => $data['mname'],
 192+ 'lname' => $data['lname'],
 193+ 'street' =>$data['street'],
 194+ 'city' => $data['city'],
 195+ 'state' => $data['state'],
 196+ 'zip' => $data['zip'],
 197+ 'country' => $data['country'],
 198+ 'fname2' => $data['fname'],
 199+ 'lname2' => $data['lname'],
 200+ 'street2' => $data['street'],
 201+ 'city2' => $data['city'],
 202+ 'state2' => $data['state'],
 203+ 'zip2' => $data['zip'],
 204+ /**
 205+ * For legacy reasons, we might get a 0-length string passed into the form for country2. If this happens, we need to set country2
 206+ * to be 'country' for downstream processing (until we fully support passing in two separate addresses). I thought about completely
 207+ * disabling country2 support in the forms, etc but realized there's a chance it'll be resurrected shortly. Hence this silly hack.
 208+ */
 209+ 'country2' => ( strlen( $data['country2'] ) ) ? $data['country2'] : $data['country'],
 210+ 'size' => $data['size'],
 211+ 'premium_language' => ( $data['premium_language'] ) ? $data['premium_language'] : 'en',
 212+ 'card_num' => str_replace( ' ', '', $data['card_num'] ),
 213+ 'card_type' => $data['card_type'],
 214+ 'expiration' => $data['mos'] . substr( $data['year'], 2, 2 ),
 215+ 'cvv' => $data['cvv'],
 216+ 'currency' => $data['currency_code'],
 217+ 'payment_method' => $data['payment_method'],
 218+ 'order_id' => $data['order_id'], //as far as I know, this won't actually ever pull anything back.
 219+ 'i_order_id' => $data['i_order_id'], //internal id for each contribution attempt
 220+ 'numAttempt' => $data['numAttempt'],
 221+ 'referrer' => $data['referrer'] ? $data['referrer'] : $wgRequest->getHeader( 'referer' ),
 222+ 'utm_source' => self::getUtmSource( $data['$utm_source'], $data['$utm_source_id'] ),
 223+ 'utm_medium' => $data['utm_medium'],
 224+ 'utm_campaign' => $data['utm_campaign'],
 225+ // try to honor the user-set language (uselang), otherwise the language set in the URL (language)
 226+ 'language' => ( $data['uselang'] ) ? $data['uselang'] : $data['language'],
 227+ 'comment-option' => $data['comment-option'],
 228+ 'comment' => $data['comment'],
 229+ 'email-opt' => $data['email-opt'],
 230+ 'test_string' => $data['process'], // for showing payflow string during testing
 231+ '_cache_' => $data['_cache_'],
 232+ 'token' => $data['token'],
 233+ 'contribution_tracking_id' => $data['contribution_tracking_id'],
 234+ 'data_hash' => $data['data_hash'],
 235+ 'action' => $data['action'],
 236+ 'gateway' => $data['gateway'], //likely to be reset shortly by setGateway();
 237+ 'owa_session' => $data['owa_session'],
 238+ 'owa_ref' => $data['owa_ref'],
 239+ );
 240+ }
181241
182242 function isSomething( $key ) {
183243 if ( array_key_exists( $key, $this->normalized ) && !empty( $this->normalized[$key] ) ) {
@@ -288,10 +348,14 @@
289349
290350 function setGateway() {
291351 //TODO: Hum. If we have some other gateway in the form data, should we go crazy here? (Probably)
292 - if ( class_exists( $this->boss ) ) {
293 - $c = $this->boss;
294 - $gateway = $c::getIdentifier();
295 - $this->setVal( 'gateway', $gateway );
 352+ if ( $this->boss == 'DonationApi' ) {
 353+ $this->setVal( 'gateway', $this->normalized['gateway'] );
 354+ } else {
 355+ if ( class_exists( $this->boss ) ) {
 356+ $c = $this->boss;
 357+ $gateway = $c::getIdentifier();
 358+ $this->setVal( 'gateway', $gateway );
 359+ }
296360 }
297361 }
298362

Follow-up revisions

RevisionCommit summaryAuthorDate
r98864follow-up to r98398, combining form and API handling for populateDatakaldari16:31, 4 October 2011

Comments

#Comment by Awjrichards (talk | contribs)   22:03, 29 September 2011

in DonationData.php, it seems that populateData_Api() and populateData_Form() do essentially the same thing, just with different data sources. Having the data field definitions in multiple places will almost certainly lead to problems (misspellings, changing something in one place but not the other, etc) - especially given that we have so many. IMHO, these functions should be collapsed into one.

Status & tagging log