public function validate(GatewayType $adapter, $normalized, &$errors) { if (!isset($normalized['amount']) || !isset($normalized['currency_code'])) { // Not enough info to validate return; } if (isset($errors['currency_code'])) { // Already displaying an error return; } $value = $normalized['amount']; if (self::isZeroIsh($value)) { $errors['amount'] = DataValidator::getErrorMessage('amount', 'not_empty', $normalized['language']); return; } $currency = $normalized['currency_code']; $min = self::convert($adapter->getGlobal('PriceFloor'), $currency); $max = self::convert($adapter->getGlobal('PriceCeiling'), $currency); if (!is_numeric($value) || $value < 0) { $errors['amount'] = WmfFramework::formatMessage('donate_interface-error-msg-invalid-amount'); } else { if ($value > $max) { // FIXME: should format the currency values in this message $errors['amount'] = WmfFramework::formatMessage('donate_interface-bigamount-error', $max, $currency, $adapter->getGlobal('MajorGiftsEmail')); } else { if ($value < $min) { $locale = $normalized['language'] . '_' . $normalized['country']; $formattedMin = self::format($min, $currency, $locale); $errors['amount'] = WmfFramework::formatMessage('donate_interface-smallamount-error', $formattedMin); } } } }
function defineTransactions() { $this->transactions = array(); $this->transactions['Donate'] = array('request' => array('amount', 'currency_code', 'country', 'business', 'cancel_return', 'cmd', 'item_name', 'item_number', 'no_note', 'return', 'custom', 'lc'), 'values' => array('business' => $this->account_config['AccountEmail'], 'cancel_return' => ResultPages::getCancelPage($this), 'cmd' => '_donations', 'item_number' => 'DONATE', 'item_name' => WmfFramework::formatMessage('donate_interface-donation-description'), 'no_note' => 0, 'return' => ResultPages::getThankYouPage($this))); $this->transactions['DonateXclick'] = array('request' => array('cmd', 'item_number', 'item_name', 'cancel_return', 'no_note', 'return', 'business', 'no_shipping', 'amount', 'currency_code', 'country', 'custom'), 'values' => array('item_number' => 'DONATE', 'item_name' => WmfFramework::formatMessage('donate_interface-donation-description'), 'cancel_return' => ResultPages::getCancelPage($this), 'no_note' => '1', 'return' => ResultPages::getThankYouPage($this), 'business' => $this->account_config['AccountEmail'], 'cmd' => '_xclick', 'no_shipping' => '1')); $this->transactions['DonateRecurring'] = array('request' => array('a3', 'currency_code', 'country', 'business', 'cancel_return', 'cmd', 'item_name', 'item_number', 'no_note', 'return', 'custom', 't3', 'p3', 'src', 'srt', 'lc'), 'values' => array('business' => $this->account_config['AccountEmail'], 'cancel_return' => ResultPages::getCancelPage($this), 'cmd' => '_xclick-subscriptions', 'item_number' => 'DONATE', 'item_name' => WmfFramework::formatMessage('donate_interface-donation-description'), 'no_note' => 0, 'return' => ResultPages::getThankYouPage($this), 't3' => 'M', 'p3' => '1', 'src' => '1', 'srt' => $this->getGlobal('RecurringLength'))); }
public static function getByCountry($country) { if (isset(self::$list[$country])) { $divisions = self::$list[$country]; // Localize subdivisions where possible if (isset(self::$keyBase[$country])) { foreach ($divisions as $abbr => $name) { $key = self::$keyBase[$country] . $abbr; if (WmfFramework::messageExists($key)) { $divisions[$abbr] = WmfFramework::formatMessage($key); } } } return $divisions; } return false; }
/** * languageSpecificFallback - returns the text of the first existant message * in the requested language. If no messages are found in that language, the * function returns the first existant fallback message. * * @param string $language the code of the requested language * @param array $msg_keys * @param array $params extra message parameters * @throws InvalidArgumentException * @return String the text of the first existant message */ public static function languageSpecificFallback($language = 'en', $msg_keys = array(), $params = array()) { if (count($msg_keys) < 1) { throw new InvalidArgumentException(__FUNCTION__ . " BAD PROGRAMMER. No message keys given."); } # look for the first message that exists foreach ($msg_keys as $m) { if (WmfFramework::messageExists($m, $language)) { return WmfFramework::formatMessage($m, $params); } } # we found nothing in the requested language, return the first fallback message that exists foreach ($msg_keys as $m) { if (WmfFramework::messageExists($m, $language)) { return WmfFramework::formatMessage($m, $params); } } # somehow we still don't have a message, return a default error message return WmfFramework::formatMessage($msg_keys[0], $params); }
protected function authorizeOnBillingAgreement() { $billingAgreementId = $this->getData_Staged('subscr_id'); $this->logger->info("Authorizing and capturing payment on billing agreement {$billingAgreementId}"); $authResponse = $this->callPwaClient('authorizeOnBillingAgreement', array('amazon_billing_agreement_id' => $billingAgreementId, 'authorization_amount' => $this->getData_Staged('amount'), 'currency_code' => $this->getData_Staged('currency_code'), 'capture_now' => true, 'authorization_reference_id' => $this->getData_Staged('order_id'), 'seller_order_id' => $this->getData_Staged('order_id'), 'seller_note' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'transaction_timeout' => 0)); return $authResponse['AuthorizeOnBillingAgreementResult']['AuthorizationDetails']; }
function defineTransactions() { $this->transactions = array(); // https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/ $this->transactions['SetExpressCheckout'] = array('request' => array('USER', 'PWD', 'VERSION', 'METHOD', 'RETURNURL', 'CANCELURL', 'REQCONFIRMSHIPPING', 'NOSHIPPING', 'LOCALECODE', 'EMAIL', 'L_PAYMENTREQUEST_0_AMT0', 'L_PAYMENTREQUEST_0_DESC0', 'PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'PAYMENTREQUEST_0_CUSTOM', 'PAYMENTREQUEST_0_DESC', 'PAYMENTREQUEST_0_INVNUM', 'PAYMENTREQUEST_0_ITEMAMT', 'PAYMENTREQUEST_0_PAYMENTACTION', 'PAYMENTREQUEST_0_PAYMENTREASON'), 'values' => array('USER' => $this->account_config['User'], 'PWD' => $this->account_config['Password'], 'VERSION' => self::API_VERSION, 'METHOD' => 'SetExpressCheckout', 'CANCELURL' => ResultPages::getCancelPage($this), 'REQCONFIRMSHIPPING' => 0, 'NOSHIPPING' => 1, 'L_PAYMENTREQUEST_0_DESC0' => WmfFramework::formatMessage('donate_interface-donation-description'), 'PAYMENTREQUEST_0_DESC' => WmfFramework::formatMessage('donate_interface-donation-description'), 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', 'PAYMENTREQUEST_0_PAYMENTREASON' => 'None'), 'response' => array('TOKEN')); // https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/ $this->transactions['SetExpressCheckout_recurring'] = array('request' => array('USER', 'PWD', 'VERSION', 'METHOD', 'RETURNURL', 'CANCELURL', 'REQCONFIRMSHIPPING', 'NOSHIPPING', 'LOCALECODE', 'EMAIL', 'L_BILLINGTYPE0', 'L_BILLINGAGREEMENTDESCRIPTION0', 'L_BILLINGAGREEMENTCUSTOM0', 'L_PAYMENTREQUEST_0_AMT0', 'L_PAYMENTREQUEST_0_NAME0', 'L_PAYMENTREQUEST_0_QTY0', 'MAXAMT', 'PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'PAYMENTREQUEST_0_ITEMAMT'), 'values' => array('USER' => $this->account_config['User'], 'PWD' => $this->account_config['Password'], 'VERSION' => self::API_VERSION, 'METHOD' => 'SetExpressCheckout', 'CANCELURL' => ResultPages::getCancelPage($this), 'REQCONFIRMSHIPPING' => 0, 'NOSHIPPING' => 1, 'L_BILLINGTYPE0' => 'RecurringPayments', 'L_BILLINGAGREEMENTDESCRIPTION0' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'L_PAYMENTREQUEST_0_DESC0' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'L_PAYMENTREQUEST_0_NAME0' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'L_PAYMENTREQUEST_0_QTY0' => 1, 'PAYMENTREQUEST_0_DESC' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', 'PAYMENTREQUEST_0_PAYMENTREASON' => 'None'), 'response' => array('TOKEN')); // Incoming parameters after returning from the PayPal workflow $this->transactions['ProcessReturn'] = array('request' => array('token', 'PayerID')); // https://developer.paypal.com/docs/classic/api/merchant/GetExpressCheckoutDetails_API_Operation_NVP/ $this->transactions['GetExpressCheckoutDetails'] = array('request' => array('USER', 'PWD', 'VERSION', 'METHOD', 'TOKEN'), 'values' => array('USER' => $this->account_config['User'], 'PWD' => $this->account_config['Password'], 'VERSION' => self::API_VERSION, 'METHOD' => 'GetExpressCheckoutDetails'), 'response' => array('ACK', 'TOKEN', 'CORRELATIONID', 'TIMESTAMP', 'CUSTOM', 'INVNUM', 'BILLINGAGREEMENTACCEPTEDSTATUS', 'REDIRECTREQUIRED', 'CHECKOUTSTATUS', 'EMAIL', 'PAYERID', 'COUNTRYCODE', 'FIRSTNAME', 'MIDDLENAME', 'LASTNAME', 'SUFFIX', 'PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'PAYMENTREQUEST_0_INVNUM', 'PAYMENTREQUEST_0_TRANSACTIONID')); // https://developer.paypal.com/docs/classic/api/merchant/DoExpressCheckoutPayment_API_Operation_NVP/ $this->transactions['DoExpressCheckoutPayment'] = array('request' => array('USER', 'PWD', 'VERSION', 'METHOD', 'TOKEN', 'PAYERID', 'PAYMENTREQUEST_0_PAYMENTACTION', 'PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'PAYMENTREQUEST_0_CUSTOM', 'PAYMENTREQUEST_0_DESC', 'PAYMENTREQUEST_0_INVNUM', 'PAYMENTREQUEST_0_ITEMAMT', 'PAYMENTREQUEST_0_PAYMENTACTION', 'PAYMENTREQUEST_0_PAYMENTREASON'), 'values' => array('USER' => $this->account_config['User'], 'PWD' => $this->account_config['Password'], 'VERSION' => self::API_VERSION, 'METHOD' => 'DoExpressCheckoutPayment', 'PAYMENTREQUEST_0_DESC' => WmfFramework::formatMessage('donate_interface-donation-description'), 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', 'PAYMENTREQUEST_0_PAYMENTREASON' => 'None')); // https://developer.paypal.com/docs/classic/api/merchant/CreateRecurringPaymentsProfile_API_Operation_NVP/ $this->transactions['CreateRecurringPaymentsProfile'] = array('request' => array('USER', 'PWD', 'VERSION', 'METHOD', 'TOKEN', 'DESC', 'PROFILESTARTDATE', 'PROFILEREFERENCE', 'AUTOBILLOUTAMT', 'BILLINGPERIOD', 'BILLINGFREQUENCY', 'TOTALBILLINGCYCLES', 'MAXFAILEDPAYMENTS', 'AMT', 'CURRENCYCODE', 'EMAIL'), 'values' => array('USER' => $this->account_config['User'], 'PWD' => $this->account_config['Password'], 'VERSION' => self::API_VERSION, 'METHOD' => 'CreateRecurringPaymentsProfile', 'DESC' => WmfFramework::formatMessage('donate_interface-monthly-donation-description'), 'AUTOBILLOUTAMT' => 'NoAutoBill', 'BILLINGPERIOD' => 'Month', 'BILLINGFREQUENCY' => 1, 'TOTALBILLINGCYCLES' => 0, 'MAXFAILEDPAYMENTS' => 3), 'response' => array('PROFILEID', 'PROFILESTATUS', 'TRANSACTIONID')); // Add the Signature field to all API calls, if necessary. // Note that this gives crappy security, vulnerable to replay attacks. // The signature is static, not a checksum of the request. if (!$this->isCertificateAuthentication()) { foreach ($this->transactions as $_name => &$info) { if (isset($info['request'])) { $info['request'][] = 'SIGNATURE'; $info['values']['SIGNATURE'] = $this->account_config['Signature']; } } } }
/** * getErrorMessage - returns the translated error message appropriate for a * validation error on the specified field, of the specified type. * @param string $field - The common name of the field containing the data * that is causing the error. * @param string $type - The type of error being caused, from a set. * Possible values are: * 'not_empty' - the value is required and not currently present * 'valid_type' - in general, the wrong format * 'calculated' - fields that failed some kind of multiple-field data * integrity check. * @param string $language MediaWiki language code * @param string $country ISO country code * @return String */ public static function getErrorMessage($field, $type, $language, $country = null) { //this is gonna get ugly up in here. //error_log( __FUNCTION__ . " $field, $type, $value " ); //NOTE: We are just using the next bit because it's convenient. //getErrorToken is actually for something entirely different: //Figuring out where on the form the error should land. $message_field = self::getErrorToken($field); if ($field === 'expiration') { ///the inevitable special case. $message_field = $field; } //postal code is a weird one. More L10n than I18n. //'donate_interface-error-msg-postal' => 'postal code', $error_message_field_key = 'donate_interface-error-msg-' . $message_field; if ($country !== null) { $translated_field_name = MessageUtils::getCountrySpecificMessage($error_message_field_key, $country, $language); } else { if (WmfFramework::messageExists($error_message_field_key, $language)) { $translated_field_name = WmfFramework::formatMessage($error_message_field_key); } else { $translated_field_name = false; } } //Empty messages should get: //'donate_interface-error-msg' => 'Please enter your $1'; //If they have no defined error message, give 'em the default. if ($type === 'not_empty') { if ($message_field != 'general' && $translated_field_name) { return WmfFramework::formatMessage('donate_interface-error-msg', $translated_field_name); } } if ($type === 'valid_type' || $type === 'calculated') { //NOTE: We are just using the next bit because it's convenient. //getErrorToken is actually for something entirely different: //Figuring out where on the form the error should land. $token = self::getErrorToken($field); $error_key_calc = 'donate_interface-error-msg-' . $token . '-calc'; if ($type === 'calculated') { // try for the special "calculated" error message. if (WmfFramework::messageExists($error_key_calc, $language)) { return WmfFramework::formatMessage($error_key_calc); } } //try for new more specific default correction message if ($message_field != 'general' && $translated_field_name && WmfFramework::messageExists('donate_interface-error-msg-field-correction', $language)) { return WmfFramework::formatMessage('donate_interface-error-msg-field-correction', $translated_field_name); } } //ultimate defaultness. return WmfFramework::formatMessage('donate_interface-error-msg-general'); }
/** * getErrorMap * * This will also return an error message if a $code is passed. * * If the error code does not exist, the default message will be returned. * * A default message should always exist with an index of 0. * * NOTE: This method will check to see if the message exists in translation * and use that message instead of the default. This would override error_map. * * @param string $code The error code to look up in the map * @param array $options * @return array|string Returns @see GatewayAdapter::$error_map */ public function getErrorMap($code = null, $options = array()) { if (is_null($code)) { return $this->error_map; } $defaults = array('translate' => false); $options = array_merge($defaults, $options); $response_message = $this->getIdentifier() . '_gateway-response-' . $code; $translatedMessage = WmfFramework::formatMessage($response_message); // FIXME: don't do this. // Check to see if an error message exists in translation if (substr($translatedMessage, 0, 3) !== '<') { // Message does not exist $translatedMessage = ''; } if (isset($this->error_map[$code])) { $mapped = $this->error_map[$code]; // Errors with complicated formatting can map to a function if (is_callable($mapped)) { return $mapped(); } $messageKey = $mapped; } else { // If the $code does not exist, use the default message $messageKey = 'donate_interface-processing-error'; } $translatedMessage = $options['translate'] && empty($translatedMessage) ? WmfFramework::formatMessage($messageKey) : $translatedMessage; // Check to see if we return the translated message. $message = $options['translate'] ? $translatedMessage : $messageKey; return $message; }
public function testTooLittleBbd() { $this->normalized['currency_code'] = 'BBD'; $this->normalized['amount'] = '2.95'; $this->validate(); $this->assertNotEmpty($this->errors, 'No error for diminutive amount (BBD)'); $formattedMin = Amount::format(3.0, 'BBD', 'en_US'); $expected = WmfFramework::formatMessage('donate_interface-smallamount-error', $formattedMin); $this->assertEquals($expected, $this->errors['amount'], 'Wrong error message for diminutive amount (BBD)'); }
/** * Sets communication status and errors for responses to NewInvoice * @param array $response */ protected function processNewInvoiceResponse($response) { // Increment sequence number so next NewInvoice call gets a new order ID $this->incrementSequenceNumber(); if (!isset($response['status'])) { $this->transaction_response->setCommunicationStatus(false); $this->logger->error('AstroPay response does not have a status code'); throw new ResponseProcessingException('AstroPay response does not have a status code', ResponseCodes::MISSING_REQUIRED_DATA); } $this->transaction_response->setCommunicationStatus(true); if ($response['status'] === '0') { if (!isset($response['link'])) { $this->logger->error('AstroPay NewInvoice success has no link'); throw new ResponseProcessingException('AstroPay NewInvoice success has no link', ResponseCodes::MISSING_REQUIRED_DATA); } } else { $logme = 'AstroPay response has non-zero status. Full response: ' . print_r($response, true); $this->logger->warning($logme); $code = 'internal-0000'; $message = $this->getErrorMapByCodeAndTranslate($code); $context = null; if (isset($response['desc'])) { // error codes are unreliable, so we have to examine the description if (preg_match('/^invoice already used/i', $response['desc'])) { $this->logger->error('Order ID collision! Starting again.'); throw new ResponseProcessingException('Order ID collision! Starting again.', ResponseCodes::DUPLICATE_ORDER_ID, array('order_id')); } else { if (preg_match('/^could not (register user|make the deposit)/i', $response['desc'])) { // AstroPay is overwhelmed. Tell the donor to try again soon. $message = WmfFramework::formatMessage('donate_interface-try-again'); } else { if (preg_match('/^user (unauthorized|blacklisted)/i', $response['desc'])) { // They are blacklisted by AstroPay for shady doings, // or listed delinquent by their government. // Either way, we can't process 'em through AstroPay $this->finalizeInternalStatus(FinalStatus::FAILED); } else { if (preg_match('/^the user limit has been exceeded/i', $response['desc'])) { // They've spent too much via AstroPay today. // Setting context to 'amount' will tell the form to treat // this like a validation error and make amount editable. $context = 'amount'; $message = WmfFramework::formatMessage('donate_interface-error-msg-limit'); } else { if (preg_match('/param x_cpf$/i', $response['desc'])) { // Something wrong with the fiscal number $context = 'fiscal_number'; $language = $this->dataObj->getVal_Escaped('language'); $country = $this->dataObj->getVal_Escaped('country'); $message = DataValidator::getErrorMessage('fiscal_number', 'calculated', $language, $country); } else { if (preg_match('/invalid control/i', $response['desc'])) { // They think we screwed up the signature. Log what we signed. $signed = AstroPaySignature::getNewInvoiceMessage($this->getData_Staged()); $signature = $this->getData_Staged('control'); $this->logger->error("{$logme} Signed message: '{$signed}' Signature: '{$signature}'"); } else { // Some less common error. Also log message at 'error' level $this->logger->error($logme); } } } } } } } $this->transaction_response->setErrors(array($code => array('message' => $message, 'debugInfo' => $logme, 'logLevel' => LogLevel::WARNING, 'context' => $context))); } }