/** * Creates an order for the specified user, and redirects to the edit page. * * @param \Drupal\user\UserInterface $user * The user to create the order for. */ public function createForUser(UserInterface $user) { $order = Order::create(['uid' => $user->id(), 'order_status' => uc_order_state_default('post_checkout')]); $order->save(); uc_order_comment_save($order->id(), \Drupal::currentUser()->id(), $this->t('Order created by the administration.'), 'admin'); return $this->redirect('entity.uc_order.edit_form', ['uc_order' => $order->id()]); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $items = \Drupal::service('uc_cart.manager')->get()->getContents(); $paypal_config = $this->config('uc_paypal.settings'); if (empty($items)) { drupal_set_message($this->t('You do not have any items in your shopping cart.')); return; } list($desc, $subtotal) = _uc_paypal_product_details($items); $order = Order::create(['uid' => $this->currentUser()->id()]); $order->save(); $nvp_request = array('METHOD' => 'SetExpressCheckout', 'RETURNURL' => Url::fromRoute('uc_paypal.ec_review', [], ['absolute' => TRUE])->toString(), 'CANCELURL' => Url::fromRoute('uc_cart.cart', [], ['absolute' => TRUE])->toString(), 'AMT' => uc_currency_format($subtotal, FALSE, FALSE, '.'), 'CURRENCYCODE' => $order->getCurrency(), 'PAYMENTACTION' => $paypal_config->get('wpp_cc_txn_type') == 'authorize' ? 'Authorization' : 'Sale', 'DESC' => substr($desc, 0, 127), 'INVNUM' => $order->id() . '-' . REQUEST_TIME, 'REQCONFIRMSHIPPING' => $paypal_config->get('ec_rqconfirmed_addr'), 'BUTTONSOURCE' => 'Ubercart_ShoppingCart_EC_US', 'NOTIFYURL' => Url::fromRoute('uc_paypal.ipn', [], ['absolute' => TRUE])->toString(), 'LANDINGPAGE' => $paypal_config->get('ec_landingpage_style')); $order->products = $items; $order->save(); $nvp_response = uc_paypal_api_request($nvp_request, $paypal_config->get('wpp_server')); if ($nvp_response['ACK'] != 'Success') { drupal_set_message($this->t('PayPal reported an error: @code: @message', ['@code' => $nvp_response['L_ERRORCODE0'], '@message' => $nvp_response['L_LONGMESSAGE0']]), 'error'); return; } $session = \Drupal::service('session'); $session->set('cart_order', $order->id()); $session->set('TOKEN', $nvp_response['TOKEN']); $sandbox = ''; if (strpos($paypal_config->get('wpp_server'), 'sandbox') > 0) { $sandbox = 'sandbox.'; } header('Location: https://www.' . $sandbox . 'paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $session->get('TOKEN')); exit; }
/** * Processes a payment POST from the CyberSource Hosted Order Page API. */ public static function post() { if (!uc_cybersource_hop_include()) { \Drupal::logger('uc_cybersource_hop')->error('Unable to receive HOP POST due to missing or unreadable HOP.php file.'); drupal_add_http_header('Status', '503 Service unavailable'); print $this->t('The site was unable to receive a HOP post because of a missing or unreadble HOP.php'); exit; } $verify = VerifyTransactionSignature($_POST); \Drupal::logger('uc_cybersource_hop')->notice('Receiving payment notification at URL for order @orderNumber', array('@orderNumber' => $_POST['orderNumber'])); if (!isset($_POST['orderNumber'])) { \Drupal::logger('uc_cybersource_hop')->error('CS HOP attempted with invalid order number.'); return; } if (!$verify) { \Drupal::logger('uc_cybersource_hop')->notice('Receiving invalid payment notification at URL for order @orderNumber. <pre>@debug</pre>', array('@orderNumber' => $_POST['orderNumber'], '@debug' => print_r($_POST, TRUE))); return; } // Assign posted variables to local variables. $decision = SafeMarkup::checkPlain($_POST['decision']); $reason_code = SafeMarkup::checkPlain($_POST['reasonCode']); $reason = _parse_cs_reason_code($reason_code); $payment_amount = SafeMarkup::checkPlain($_POST['orderAmount']); $payment_currency = SafeMarkup::checkPlain($_POST['paymentCurrency']); $request_id = SafeMarkup::checkPlain($_POST['requestID']); $request_token = SafeMarkup::checkPlain($_POST['orderPage_requestToken']); $reconciliation_id = SafeMarkup::checkPlain($_POST['reconciliationID']); $order_id = SafeMarkup::checkPlain($_POST['orderNumber']); $payer_email = SafeMarkup::checkPlain($_POST['billTo_email']); $order = Order::load($_POST['orderNumber']); switch ($decision) { case 'ACCEPT': \Drupal::logger('uc_cybersource_hop')->notice('CyberSource verified successful payment.'); $duplicate = (bool) db_query_range('SELECT 1 FROM {uc_payment_cybersource_hop_post} WHERE order_id = :order_id AND decision = :decision', 0, 1, array(':order_id' => $order_id, ':decision' => 'ACCEPT'))->fetchField(); if ($duplicate) { \Drupal::logger('uc_cybersource_hop')->notice('CS HOP transaction for order @order-id has been processed before.', array('@order_id' => $order_id)); return; } db_insert('uc_payment_cybersource_hop_post')->fields(array('order_id' => $order_id, 'request_id' => $request_id, 'request_token' => $request_token, 'reconciliation_id' => $reconciliation_id, 'gross' => $payment_amount, 'decision' => $decision, 'reason_code' => $reason_code, 'payer_email' => $payer_email, 'received' => REQUEST_TIME))->execute(); $comment = $this->t('CyberSource request ID: @txn_id', array('@txn_id' => $request_id)); uc_payment_enter($order_id, 'cybersource_hop', $payment_amount, $order->getUserId(), NULL, $comment); uc_cart_complete_sale($order); uc_order_comment_save($order_id, 0, $this->t('Payment of @amount @currency submitted through CyberSource with request ID @rid.', array('@amount' => $payment_amount, '@currency' => $payment_currency, '@rid' => $request_id)), 'order', 'payment_received'); break; case 'ERROR': uc_order_comment_save($order_id, 0, $this->t("Payment error:@reason with request ID @rid", array('@reason' => $reason, '@rid' => '@request_id')), 'admin'); break; case 'REJECT': uc_order_comment_save($order_id, 0, $this->t("Payment is rejected:@reason with request ID @rid", array('@reason' => $reason, '@rid' => '@request_id')), 'admin'); break; case 'REVIEW': $order->setStatusId('review')->save(); uc_order_comment_save($order_id, 0, $this->t('Payment is in review & not complete: @reason. Request ID @rid', array('@reason' => $reason, '@rid' => '@request_id')), 'admin'); break; } }
/** * Tests customer overview. */ public function testCustomerAdminPages() { $this->drupalLogin($this->adminUser); $country = Country::load('US'); Order::create(array('uid' => $this->customer->id(), 'billing_country' => $country->id(), 'billing_zone' => 'AK'))->save(); $this->drupalGet('admin/store/customers/view'); $this->assertResponse(200); $this->assertLinkByHref('user/' . $this->customer->id()); $this->assertText($country->getZones()['AK']); $this->assertText($country->label()); }
public function testCheckoutFileDownload() { $this->drupalLogin($this->adminUser); $method = $this->createPaymentMethod('other'); // Add file download to the test product. $filename = $this->getTestFile(); $this->drupalPostForm('node/' . $this->product->id() . '/edit/features', array('feature' => 'file'), t('Add')); $this->drupalPostForm(NULL, array('uc_file_filename' => $filename), t('Save feature')); // Process an anonymous, shippable order. $order = $this->createOrder(['uid' => 0, 'payment_method' => $method['id']]); $order->products[1]->data->shippable = 1; $order->save(); uc_payment_enter($order->id(), $method['id'], $order->getTotal()); // Find the order uid. $uid = db_query('SELECT uid FROM {uc_orders} ORDER BY order_id DESC')->fetchField(); // @todo Re-enable when Rules is available. // $account = User::load($uid); // $this->assertTrue($account->hasFile($fid), 'New user was granted file.'); $order = Order::load($order->id()); $this->assertEqual($order->getStatusId(), 'payment_received', 'Shippable order was set to payment received.'); // Test that the file shows up on the user's purchased files list. //$this->drupalGet('user/' . $uid . '/purchased-files'); //$this->assertText($filename, 'File found in list of purchased files.'); // 4 e-mails: new account, customer invoice, admin invoice, file download. $this->assertMailString('subject', 'Account details', 4, 'New account email was sent'); $this->assertMailString('subject', 'Your Order at Ubercart', 4, 'Customer invoice was sent'); $this->assertMailString('subject', 'New Order at Ubercart', 4, 'Admin notification was sent'); // @todo Re-enable when Rules is available. // $this->assertMailString('subject', 'File Downloads', 4, 'File download notification was sent'); \Drupal::state()->set('system.test_email_collector', []); // Test again with an existing authenticated user and a non-shippable order. $order = $this->createOrder(array('uid' => 0, 'primary_email' => $this->customer->getEmail(), 'payment_method' => $method['id'])); $order->products[2]->data->shippable = 0; $order->save(); uc_payment_enter($order->id(), $method['id'], $order->getTotal()); $account = User::load($this->customer->id()); // @todo Re-enable when Rules is available. // $this->assertTrue($account->hasFile($fid), 'Existing user was granted file.'); $order = Order::load($order->id()); $this->assertEqual($order->getStatusId(), 'completed', 'Non-shippable order was set to completed.'); // 3 e-mails: customer invoice, admin invoice, file download. $this->assertNoMailString('subject', 'Account details', 3, 'New account email was sent'); $this->assertMailString('subject', 'Your Order at Ubercart', 3, 'Customer invoice was sent'); $this->assertMailString('subject', 'New Order at Ubercart', 3, 'Admin notification was sent'); // @todo Re-enable when Rules is available. // $this->assertMailString('subject', 'File Downloads', 3, 'File download notification was sent'); }
public function testShipmentsUI() { $this->drupalLogin($this->adminUser); $method = $this->createPaymentMethod('other'); // Process an anonymous, shippable order. $order = Order::create(['uid' => 0, 'primary_email' => $this->randomString() . '@example.org', 'payment_method' => $method['id']]); // Add three more products to use for our tests. $products = array(); for ($i = 1; $i <= 4; $i++) { $product = $this->createProduct(array('uid' => $this->adminUser->id(), 'promote' => 0)); $order->products[$i] = OrderProduct::create(array('nid' => $product->nid->target_id, 'title' => $product->title->value, 'model' => $product->model, 'qty' => 1, 'cost' => $product->cost->value, 'price' => $product->price->value, 'weight' => $product->weight, 'data' => [])); $order->products[$i]->data->shippable = 1; } $order->save(); $order = Order::load($order->id()); uc_payment_enter($order->id(), $method['id'], $order->getTotal()); // Now quickly package all the products in this order. $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); $this->drupalPostForm(NULL, array('shipping_types[small_package][table][1][checked]' => 1, 'shipping_types[small_package][table][2][checked]' => 1, 'shipping_types[small_package][table][3][checked]' => 1, 'shipping_types[small_package][table][4][checked]' => 1), t('Create one package')); // Test "Ship" operations for this package. $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); $this->assertLink(t('Ship')); $this->clickLink(t('Ship')); $this->assertUrl('admin/store/orders/' . $order->id() . '/shipments/new?pkgs=1'); foreach ($order->products as $sequence => $item) { $this->assertText($item->qty->value . ' x ' . $item->model->value, 'Product quantity x SKU found.'); // Test for weight here too? How do we compute this? } // We're shipping a specific package, so it should already be checked. foreach ($order->products as $sequence => $item) { $this->assertFieldByName('shipping_types[small_package][table][1][checked]', 1, 'Package is available for shipping.'); } $this->assertFieldByName('method', 'manual', 'Manual shipping method selected.'); // // Test presence and operation of ship operation on order admin View. // $this->drupalGet('admin/store/orders/view'); $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/shipments'); // Test action. $this->clickLink(t('Ship')); $this->assertResponse(200); $this->assertUrl('admin/store/orders/' . $order->id() . '/shipments/new'); $this->assertText('No shipments have been made for this order.', 'Ship action found.'); $this->assertText($order->products[1]->qty->value . ' x ' . $order->products[1]->model->value, 'Product quantity x SKU found.'); $this->assertFieldByName('method', 'manual', 'Manual shipping method selected.'); // Test reaching this through the shipments tab too ... }
/** * Finalizes 2checkout transaction. */ public function complete($cart_id = 0) { $cart_config = \Drupal::config('uc_cart.settings'); $module_config = \Drupal::config('uc_2checkout.settings'); \Drupal::logger('2Checkout')->notice('Receiving new order notification for order !order_id.', array('!order_id' => SafeMarkup::checkPlain($_REQUEST['merchant_order_id']))); $order = Order::load($_REQUEST['merchant_order_id']); if (!$order || $order->getStateId() != 'in_checkout') { return t('An error has occurred during payment. Please contact us to ensure your order has submitted.'); } $key = $_REQUEST['key']; $order_number = $module_config->get('demo') ? 1 : $_REQUEST['order_number']; $valid = md5($module_config->get('secret_word') . $_REQUEST['sid'] . $order_number . $_REQUEST['total']); if (Unicode::strtolower($key) != Unicode::strtolower($valid)) { uc_order_comment_save($order->id(), 0, t('Attempted unverified 2Checkout completion for this order.'), 'admin'); throw new AccessDeniedHttpException(); } if ($_REQUEST['demo'] == 'Y' xor $module_config->get('demo')) { \Drupal::logger('uc_2checkout')->error('The 2checkout payment for order <a href="@order_url">@order_id</a> demo flag was set to %flag, but the module is set to %mode mode.', array('@order_url' => url('admin/store/orders/' . $order->id()), '@order_id' => $order->id(), '%flag' => $_REQUEST['demo'] == 'Y' ? 'Y' : 'N', '%mode' => $module_config->get('demo') ? 'Y' : 'N')); if (!$module_config->get('demo')) { throw new AccessDeniedHttpException(); } } $order->billing_street1 = $_REQUEST['street_address']; $order->billing_street2 = $_REQUEST['street_address2']; $order->billing_city = $_REQUEST['city']; $order->billing_postal_code = $_REQUEST['zip']; $order->billing_phone = $_REQUEST['phone']; $order->billing_zone = $_REQUEST['state']; $order->billing_country = $_REQUEST['country']; $order->save(); if (Unicode::strtolower($_REQUEST['email']) !== Unicode::strtolower($order->getEmail())) { uc_order_comment_save($order->id(), 0, t('Customer used a different e-mail address during payment: !email', array('!email' => SafeMarkup::checkPlain($_REQUEST['email']))), 'admin'); } if ($_REQUEST['credit_card_processed'] == 'Y' && is_numeric($_REQUEST['total'])) { $comment = t('Paid by !type, 2Checkout.com order #!order.', array('!type' => $_REQUEST['pay_method'] == 'CC' ? t('credit card') : t('echeck'), '!order' => SafeMarkup::checkPlain($_REQUEST['order_number']))); uc_payment_enter($order->id(), '2checkout', $_REQUEST['total'], 0, NULL, $comment); } else { drupal_set_message(t('Your order will be processed as soon as your payment clears at 2Checkout.com.')); uc_order_comment_save($order->id(), 0, t('!type payment is pending approval at 2Checkout.com.', array('!type' => $_REQUEST['pay_method'] == 'CC' ? t('Credit card') : t('eCheck'))), 'admin'); } // Empty that cart... uc_cart_empty($cart_id); // Add a comment to let sales team know this came in through the site. uc_order_comment_save($order->id(), 0, t('Order created through website.'), 'admin'); $build = uc_cart_complete_sale($order, $cart_config->get('new_customer_login')); return $build; }
/** * {@inheritdoc} */ public function render(ResultRow $values) { $oid = $values->{$this->aliases['order_id']}; $order = Order::load($oid); $total = 0; foreach ($order->products as $product) { $unit_conversion = uc_weight_conversion($product->weight_units, $this->options['weight_units']); $total += $product->qty * $product->weight * $unit_conversion; } $this->field_alias = 'order_weight'; $values->{$this->field_alias} = $total; if ($this->options['format'] == 'numeric') { return parent::render($values); } if ($this->options['format'] == 'uc_weight') { return uc_weight_format($values->{$this->field_alias}, $this->options['weight_units']); } }
public function testCheckoutRoleAssignment() { // Add role assignment to the test product. $rid = $this->drupalCreateRole(array('access content')); $this->drupalLogin($this->adminUser); $this->drupalPostForm('node/' . $this->product->id() . '/edit/features', array('feature' => 'role'), t('Add')); $this->drupalPostForm(NULL, array('uc_role_role' => $rid), t('Save feature')); // Process an anonymous, shippable order. $order = $this->createOrder(); $order->products[1]->data->shippable = 1; $order->save(); uc_payment_enter($order->id(), 'SimpleTest', $order->getTotal()); // Find the order uid. $uid = db_query('SELECT uid FROM {uc_orders} ORDER BY order_id DESC')->fetchField(); $account = User::load($uid); // @todo Re-enable when Rules is available. // $this->assertTrue($account->hasRole($rid), 'New user was granted role.'); $order = Order::load($order->id()); $this->assertEqual($order->getStatusId(), 'payment_received', 'Shippable order was set to payment received.'); // 4 e-mails: new account, customer invoice, admin invoice, role assignment $this->assertMailString('subject', 'Account details', 4, 'New account email was sent'); $this->assertMailString('subject', 'Your Order at Ubercart', 4, 'Customer invoice was sent'); $this->assertMailString('subject', 'New Order at Ubercart', 4, 'Admin notification was sent'); // @todo Re-enable when Rules is available. // $this->assertMailString('subject', 'role granted', 4, 'Role assignment notification was sent'); \Drupal::state()->set('system.test_email_collector', []); // Test again with an existing authenticated user and a non-shippable order. $order = $this->createOrder(array('primary_email' => $this->customer->getEmail())); $order->products[2]->data->shippable = 0; $order->save(); uc_payment_enter($order->id(), 'SimpleTest', $order->getTotal()); $account = User::load($this->customer->id()); // @todo Re-enable when Rules is available. // $this->assertTrue($account->hasRole($rid), 'Existing user was granted role.'); $order = Order::load($order->id()); $this->assertEqual($order->getStatusId(), 'completed', 'Non-shippable order was set to completed.'); // 3 e-mails: customer invoice, admin invoice, role assignment $this->assertNoMailString('subject', 'Account details', 4, 'New account email was sent'); $this->assertMailString('subject', 'Your Order at Ubercart', 4, 'Customer invoice was sent'); $this->assertMailString('subject', 'New Order at Ubercart', 4, 'Admin notification was sent'); // @todo Re-enable when Rules is available. // $this->assertMailString('subject', 'role granted', 4, 'Role assignment notification was sent'); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $uid = $this->currentUser()->id(); if (!$form_state->isValueEmpty('order_comment')) { uc_order_comment_save($form_state->getValue('order_id'), $uid, $form_state->getValue('order_comment'), 'order', $form_state->getValue('status'), $form_state->getValue('notify')); } if (!$form_state->isValueEmpty('admin_comment')) { uc_order_comment_save($form_state->getValue('order_id'), $uid, $form_state->getValue('admin_comment')); } if ($form_state->getValue('status') != $form_state->getValue('current_status')) { Order::load($form_state->getValue('order_id'))->setStatusId($form_state->getValue('status'))->save(); if ($form_state->isValueEmpty('order_comment')) { uc_order_comment_save($form_state->getValue('order_id'), $uid, '-', 'order', $form_state->getValue('status'), $form_state->getValue('notify')); } } // Let Rules send email if requested. // if ($form_state->getValue('notify')) { // $order = Order::load($form_state->getValue('order_id')); // rules_invoke_event('uc_order_status_email_update', $order); // } drupal_set_message($this->t('Order updated.')); }
/** * Tests for CashOnDelivery payment method. */ public function testCashOnDelivery() { $this->drupalGet('admin/store/config/payment/add/cod'); $this->assertFieldByName('settings[policy]', 'Full payment is expected upon delivery or prior to pick-up.', 'Default COD policy found.'); $cod = $this->createPaymentMethod('cod', ['settings[policy]' => $this->randomString()]); // @todo: Test enabling delivery date on settings page. // Test checkout page. $this->drupalGet('cart/checkout'); $this->assertFieldByName('panes[payment][payment_method]', $cod['id'], 'COD payment method is selected at checkout.'); $this->assertEscaped($cod['settings[policy]'], 'COD policy found at checkout.'); // Test review order page. $this->drupalPostForm(NULL, array(), 'Review order'); $this->assertText('Cash on delivery', 'COD payment method found on review page.'); $this->drupalPostForm(NULL, array(), 'Submit order'); // Test user order view. $order = Order::load(1); $this->assertEqual($order->getPaymentMethodId(), $cod['id'], 'Order has COD payment method.'); $this->drupalGet('user/' . $order->getOwnerId() . '/orders/' . $order->id()); $this->assertText('Method: Cash on delivery', 'COD payment method displayed.'); // Test admin order view. $this->drupalGet('admin/store/orders/' . $order->id()); $this->assertText('Method: Cash on delivery', 'COD payment method displayed.'); }
/** * Tests for Other payment method. */ public function testOther() { $other = $this->createPaymentMethod('other'); // Test checkout page $this->drupalGet('cart/checkout'); $this->assertFieldByName('panes[payment][payment_method]', $other['id'], 'Other payment method is selected at checkout.'); // Test review order page $this->drupalPostForm(NULL, array(), 'Review order'); $this->assertText('Other', 'Other payment method found on review page.'); $this->drupalPostForm(NULL, array(), 'Submit order'); // Test user order view $order = Order::load(1); $this->assertEqual($order->getPaymentMethodId(), $other['id'], 'Order has other payment method.'); $this->drupalGet('user/' . $order->getOwnerId() . '/orders/' . $order->id()); $this->assertText('Method: Other', 'Other payment method displayed.'); // Test admin order view $this->drupalGet('admin/store/orders/' . $order->id()); $this->assertText('Method: Other', 'Other payment method displayed.'); $this->drupalGet('admin/store/orders/' . $order->id() . '/edit'); $this->assertFieldByName('payment_method', $other['id'], 'Other payment method is selected in the order edit form.'); $edit = array('payment_details[description]' => $this->randomString()); $this->drupalPostForm(NULL, array(), 'Save changes'); // @todo: Test storage of payment details. }
/** * Tests for Check payment method. */ public function testCheck() { $this->drupalGet('admin/store/config/payment/add/check'); $this->assertText('Check'); $this->assertFieldByName('settings[policy]', 'Personal and business checks will be held for up to 10 business days to ensure payment clears before an order is shipped.', 'Default check payment policy found.'); $edit = ['id' => strtolower($this->randomMachineName()), 'label' => $this->randomString(), 'settings[policy]' => $this->randomString()]; // Fill in and save the check address settings. $address = new Address(); $address->first_name = $this->randomMachineName(6); $address->company = $this->randomMachineName(10); $address->street1 = mt_rand(100, 1000) . ' ' . $this->randomMachineName(10); $address->street2 = 'Suite ' . mt_rand(100, 999); $address->city = $this->randomMachineName(10); $address->postal_code = mt_rand(10000, 99999); $country_id = array_rand(\Drupal::service('country_manager')->getEnabledList()); $address->country = $country_id; $this->drupalPostAjaxForm(NULL, ['settings[address][country]' => $address->country], 'settings[address][country]'); $edit += array('settings[name]' => $address->first_name, 'settings[address][company]' => $address->company, 'settings[address][street1]' => $address->street1, 'settings[address][street2]' => $address->street2, 'settings[address][city]' => $address->city, 'settings[address][country]' => $address->country, 'settings[address][postal_code]' => $address->postal_code); // Don't try to set the zone unless the country has zones! $zone_list = \Drupal::service('country_manager')->getZoneList($country_id); if (!empty($zone_list)) { $address->zone = array_rand($zone_list); $edit += array('settings[address][zone]' => $address->zone); } $this->drupalPostForm(NULL, $edit, 'Save'); // Test that check settings show up on checkout page. $this->drupalGet('cart/checkout'); $this->assertFieldByName('panes[payment][payment_method]', $edit['id'], 'Check payment method is selected at checkout.'); $this->assertText('Checks should be made out to:'); $this->assertRaw((string) $address, 'Properly formatted check mailing address found.'); $this->assertEscaped($edit['settings[policy]'], 'Check payment policy found at checkout.'); // Test that check settings show up on review order page. $this->drupalPostForm(NULL, array(), 'Review order'); $this->assertText('Check', 'Check payment method found on review page.'); $this->assertText('Mail to', 'Check payment method help text found on review page.'); $this->assertRaw((string) $address, 'Properly formatted check mailing address found.'); $this->drupalPostForm(NULL, array(), 'Submit order'); // Test user order view. $order = Order::load(1); $this->assertEqual($order->getPaymentMethodId(), $edit['id'], 'Order has check payment method.'); $this->drupalGet('user/' . $order->getOwnerId() . '/orders/' . $order->id()); $this->assertText('Method: Check', 'Check payment method displayed.'); // Test admin order view - receive check. $this->drupalGet('admin/store/orders/' . $order->id()); $this->assertText('Method: Check', 'Check payment method displayed.'); $this->assertLink('Receive Check'); $this->clickLink('Receive Check'); $this->assertFieldByName('amount', number_format($order->getTotal(), 2, '.', ''), 'Amount field defaults to order total.'); // Random receive date between tomorrow and 1 year from now. $receive_date = strtotime('now +' . mt_rand(1, 365) . ' days'); $formatted = \Drupal::service('date.formatter')->format($receive_date, 'uc_store'); $edit = array('comment' => $this->randomString(), 'clear_date[date]' => date('Y-m-d', $receive_date)); $this->drupalPostForm(NULL, $edit, 'Receive check'); $this->assertNoLink('Receive Check'); $this->assertText('Clear Date: ' . $formatted, 'Check clear date found.'); // Test that user order view shows check received. $this->drupalGet('user/' . $order->getOwnerId() . '/orders/' . $order->id()); $this->assertText('Check received'); $this->assertText('Expected clear date:'); $this->assertText($formatted, 'Check clear date found.'); }
/** * Creates a new order directly, without going through checkout. */ protected function createOrder($edit = []) { if (empty($edit['primary_email'])) { $edit['primary_email'] = $this->randomString() . '@example.org'; } $order = Order::create($edit); if (!isset($edit['products'])) { $order->products[] = OrderProduct::create(array('nid' => $this->product->nid->target_id, 'title' => $this->product->title->value, 'model' => $this->product->model, 'qty' => 1, 'cost' => $this->product->cost->value, 'price' => $this->product->price->value, 'weight' => $this->product->weight, 'data' => [])); } $order->save(); return Order::load($order->id()); }
/** * Link a completed sale to a user. * * @param \Drupal\uc_order\Entity\Order $order * The order entity that has just been completed. */ protected function completeSaleAccount($order) { // Order already has a user ID, so the user was logged in during checkout. if ($order->getOwnerId()) { $order->data->complete_sale = 'logged_in'; return; } // Email address matches an existing account. if ($account = user_load_by_mail($order->getEmail())) { $order->setOwner($account); $order->data->complete_sale = 'existing_user'; return; } // Set up a new user. $cart_config = \Drupal::config('uc_cart.settings'); $fields = array('name' => uc_store_email_to_username($order->getEmail()), 'mail' => $order->getEmail(), 'init' => $order->getEmail(), 'pass' => user_password(), 'roles' => array(), 'status' => $cart_config->get('new_customer_status_active') ? 1 : 0); // Override the username, if specified. if (isset($order->data->new_user_name)) { $fields['name'] = $order->data->new_user_name; } // Create the account. $account = User::create($fields); $account->save(); // Override the password, if specified. if (isset($order->data->new_user_hash)) { db_query('UPDATE {users_field_data} SET pass = :hash WHERE uid = :uid', [':hash' => $order->data->new_user_hash, ':uid' => $account->id()]); $account->password = t('Your password'); } else { $account->password = $fields['pass']; $order->password = $fields['pass']; } // Send the customer their account details if enabled. if ($cart_config->get('new_customer_email')) { $type = $cart_config->get('new_customer_status_active') ? 'register_no_approval_required' : 'register_pending_approval'; \Drupal::service('plugin.manager.mail')->mail('user', $type, $order->getEmail(), uc_store_mail_recipient_langcode($order->getEmail()), array('account' => $account), uc_store_email_from()); } $order->setOwner($account); $order->data->new_user_name = $fields['name']; $order->data->complete_sale = 'new_user'; }
public function testTaxDisplay() { $this->drupalLogin($this->adminUser); // Enable a payment method for the payment preview checkout pane. $edit = array('methods[check][status]' => 1); $this->drupalPostForm('admin/store/config/payment', $edit, t('Save configuration')); // Create a 20% inclusive tax rate. $rate = (object) array('name' => $this->randomMachineName(8), 'rate' => 0.2, 'taxed_product_types' => array('product'), 'taxed_line_items' => array(), 'weight' => 0, 'shippable' => 0, 'display_include' => 1, 'inclusion_text' => ''); uc_tax_rate_save($rate); $this->drupalGet('admin/store/config/taxes'); $this->assertText($rate->name, 'Tax was saved successfully.'); // $this->drupalGet("admin/store/config/taxes/manage/uc_tax_$rate->id"); // $this->assertText(t('Conditions'), 'Rules configuration linked to tax.'); $this->addToCart($this->product); // Manually step through checkout. $this->checkout() doesn't know about taxes. $this->drupalPostForm('cart', array(), 'Checkout'); $this->assertText(t('Enter your billing address and information here.'), 'Viewed cart page: Billing pane has been displayed.'); $this->assertRaw($rate->name, 'Tax line item displayed.'); $this->assertRaw(uc_currency_format($rate->rate * $this->product->price->value), 'Correct tax amount displayed.'); // Submit the checkout page. $edit = $this->populateCheckoutForm(); $this->drupalPostForm('cart/checkout', $edit, t('Review order')); $this->assertRaw(t('Your order is almost complete.')); $this->assertRaw($rate->name, 'Tax line item displayed.'); $this->assertRaw(uc_currency_format($rate->rate * $this->product->price->value), 'Correct tax amount displayed.'); // Complete the review page. $this->drupalPostForm(NULL, array(), t('Submit order')); $order_ids = \Drupal::entityQuery('uc_order')->condition('delivery_first_name', $edit['panes[delivery][first_name]'])->execute(); $order_id = reset($order_ids); if ($order_id) { $this->pass(SafeMarkup::format('Order %order_id has been created', ['%order_id' => $order_id])); $this->drupalGet('admin/store/orders/' . $order_id . '/edit'); $this->assertTaxLineCorrect($this->loadTaxLine($order_id), $rate->rate, 'on initial order load'); $this->drupalPostForm('admin/store/orders/' . $order_id . '/edit', array(), t('Save changes')); $this->assertText(t('Order changes saved.')); $this->assertTaxLineCorrect($this->loadTaxLine($order_id), $rate->rate, 'after saving order'); // Change tax rate and ensure order doesn't change. $oldrate = $rate->rate; $rate->rate = 0.1; $rate = uc_tax_rate_save($rate); // Save order because tax changes are only updated on save. $this->drupalPostForm('admin/store/orders/' . $order_id . '/edit', array(), t('Save changes')); $this->assertText(t('Order changes saved.')); $this->assertTaxLineCorrect($this->loadTaxLine($order_id), $oldrate, 'after rate change'); // Change taxable products and ensure order doesn't change. $class = $this->createProductClass(); $rate->taxed_product_types = array($class->getEntityTypeId()); uc_tax_rate_save($rate); // entity_flush_caches(); $this->drupalPostForm('admin/store/orders/' . $order_id . '/edit', array(), t('Save changes')); $this->assertText(t('Order changes saved.')); $this->assertTaxLineCorrect($this->loadTaxLine($order_id), $oldrate, 'after applicable product change'); // Change order Status back to in_checkout and ensure tax-rate changes now update the order. \Drupal\uc_order\Entity\Order::load($order_id)->setStatusId('in_checkout')->save(); $this->drupalPostForm('admin/store/orders/' . $order_id . '/edit', array(), t('Save changes')); $this->assertText(t('Order changes saved.')); $this->assertFalse($this->loadTaxLine($order_id), 'The tax line was removed from the order when order status changed back to in_checkout.'); // Restore taxable product and ensure new tax is added. $rate->taxed_product_types = array('product'); uc_tax_rate_save($rate); $this->drupalPostForm('admin/store/orders/' . $order_id . '/edit', array(), t('Save changes')); $this->assertText(t('Order changes saved.')); $this->assertTaxLineCorrect($this->loadTaxLine($order_id), $rate->rate, 'when order status changed back to in_checkout'); } else { $this->fail('No order was created.'); } }
/** * Processes Instant Payment Notifications from PayPal. * * @param array $ipn * The IPN data. */ protected function processIpn($ipn) { $amount = $ipn['mc_gross']; $email = !empty($ipn['business']) ? $ipn['business'] : $ipn['receiver_email']; $txn_id = $ipn['txn_id']; if (!isset($ipn['invoice'])) { \Drupal::logger('uc_paypal')->error('IPN attempted with invalid order ID.'); return; } // Extract order and cart IDs. $order_id = $ipn['invoice']; if (strpos($order_id, '-') > 0) { list($order_id, $cart_id) = explode('-', $order_id); \Drupal::service('session')->set('uc_cart_id', $cart_id); } $order = Order::load($order_id); if (!$order) { \Drupal::logger('uc_paypal')->error('IPN attempted for non-existent order @order_id.', ['@order_id' => $order_id]); return; } // @todo Send method name and order ID in the IPN URL? $config = \Drupal::service('plugin.manager.uc_payment.method')->createFromOrder($order)->getConfiguration(); // Optionally log IPN details. if (!empty($config['wps_debug_ipn'])) { \Drupal::logger('uc_paypal')->notice('Receiving IPN at URL for order @order_id. <pre>@debug</pre>', ['@order_id' => $order_id, '@debug' => print_r($ipn, TRUE)]); } // Express Checkout IPNs may not have the WPS email stored. But if it is, // make sure that the right account is being paid. if (!empty($config['wps_email']) && Unicode::strtolower($email) != Unicode::strtolower($config['wps_email'])) { \Drupal::logger('uc_paypal')->error('IPN for a different PayPal account attempted.'); return; } // Determine server. if (empty($data['test_ipn'])) { $host = 'https://www.paypal.com/cgi-bin/webscr'; } else { $host = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; } // POST IPN data back to PayPal to validate. try { $response = \Drupal::httpClient()->request('POST', $host, ['form_params' => ['cmd' => '_notify-validate'] + $ipn]); } catch (TransferException $e) { \Drupal::logger('uc_paypal')->error('IPN validation failed with HTTP error %error.', ['%error' => $e->getMessage()]); return; } // Check IPN validation response to determine if the IPN was valid.. if ($response->getBody() != 'VERIFIED') { \Drupal::logger('uc_paypal')->error('IPN transaction failed verification.'); uc_order_comment_save($order_id, 0, $this->t('An IPN transaction failed verification for this order.'), 'admin'); return; } // Check for a duplicate transaction ID. $duplicate = (bool) db_query_range('SELECT 1 FROM {uc_payment_paypal_ipn} WHERE txn_id = :id AND status <> :status', 0, 1, [':id' => $txn_id, ':status' => 'Pending'])->fetchField(); if ($duplicate) { if ($order->getPaymentMethodId() != 'credit') { \Drupal::logger('uc_paypal')->notice('IPN transaction ID has been processed before.'); } return; } db_insert('uc_payment_paypal_ipn')->fields(array('order_id' => $order_id, 'txn_id' => $txn_id, 'txn_type' => $ipn['txn_type'], 'mc_gross' => $amount, 'status' => $ipn['payment_status'], 'receiver_email' => $email, 'payer_email' => $ipn['payer_email'], 'received' => REQUEST_TIME))->execute(); switch ($ipn['payment_status']) { case 'Canceled_Reversal': uc_order_comment_save($order_id, 0, $this->t('PayPal has canceled the reversal and returned @amount @currency to your account.', ['@amount' => uc_currency_format($amount, FALSE), '@currency' => $ipn['mc_currency']]), 'admin'); break; case 'Completed': if (abs($amount - $order->getTotal()) > 0.01) { \Drupal::logger('uc_paypal')->warning('Payment @txn_id for order @order_id did not equal the order total.', ['@txn_id' => $txn_id, '@order_id' => $order->id(), 'link' => Link::createFromRoute($this->t('view'), 'entity.uc_order.canonical', ['uc_order' => $order->id()])->toString()]); } $comment = $this->t('PayPal transaction ID: @txn_id', ['@txn_id' => $txn_id]); uc_payment_enter($order_id, 'paypal_wps', $amount, $order->getOwnerId(), NULL, $comment); uc_order_comment_save($order_id, 0, $this->t('PayPal IPN reported a payment of @amount @currency.', ['@amount' => uc_currency_format($amount, FALSE), '@currency' => $ipn['mc_currency']])); break; case 'Denied': uc_order_comment_save($order_id, 0, $this->t("You have denied the customer's payment."), 'admin'); break; case 'Expired': uc_order_comment_save($order_id, 0, $this->t('The authorization has failed and cannot be captured.'), 'admin'); break; case 'Failed': uc_order_comment_save($order_id, 0, $this->t("The customer's attempted payment from a bank account failed."), 'admin'); break; case 'Pending': $order->setStatusId('paypal_pending')->save(); uc_order_comment_save($order_id, 0, $this->t('Payment is pending at PayPal: @reason', ['@reason' => $this->pendingMessage($ipn['pending_reason'])]), 'admin'); break; // You, the merchant, refunded the payment. // You, the merchant, refunded the payment. case 'Refunded': $comment = $this->t('PayPal transaction ID: @txn_id', ['@txn_id' => $txn_id]); uc_payment_enter($order_id, 'paypal_wps', $amount, $order->getOwnerId(), NULL, $comment); break; case 'Reversed': \Drupal::logger('uc_paypal')->error('PayPal has reversed a payment!'); uc_order_comment_save($order_id, 0, $this->t('Payment has been reversed by PayPal: @reason', ['@reason' => $this->reversalMessage($ipn['reason_code'])]), 'admin'); break; case 'Processed': uc_order_comment_save($order_id, 0, $this->t('A payment has been accepted.'), 'admin'); break; case 'Voided': uc_order_comment_save($order_id, 0, $this->t('The authorization has been voided.'), 'admin'); break; } }
protected function ucCreateOrder($customer) { $order = Order::create(array('uid' => $customer->id())); $order->save(); uc_order_comment_save($order->id(), 0, t('Order created programmatically.'), 'admin'); $order_ids = \Drupal::entityQuery('uc_order')->condition('order_id', $order->id())->execute(); $this->assertTrue(in_array($order->id(), $order_ids), SafeMarkup::format('Found order ID @order_id', ['@order_id' => $order->id()])); $country_manager = \Drupal::service('country_manager'); $country = array_rand($country_manager->getEnabledList()); $zones = $country_manager->getZoneList($country); $delivery_address = new Address(); $delivery_address->first_name = $this->randomMachineName(12); $delivery_address->last_name = $this->randomMachineName(12); $delivery_address->street1 = $this->randomMachineName(12); $delivery_address->street2 = $this->randomMachineName(12); $delivery_address->city = $this->randomMachineName(12); $delivery_address->zone = array_rand($zones); $delivery_address->postal_code = mt_rand(10000, 99999); $delivery_address->country = $country; $billing_address = new Address(); $billing_address->first_name = $this->randomMachineName(12); $billing_address->last_name = $this->randomMachineName(12); $billing_address->street1 = $this->randomMachineName(12); $billing_address->street2 = $this->randomMachineName(12); $billing_address->city = $this->randomMachineName(12); $billing_address->zone = array_rand($zones); $billing_address->postal_code = mt_rand(10000, 99999); $billing_address->country = $country; $order->setAddress('delivery', $delivery_address)->setAddress('billing', $billing_address)->save(); // Force the order to load from the DB instead of the entity cache. $db_order = \Drupal::entityManager()->getStorage('uc_order')->loadUnchanged($order->id()); // Compare delivery and billing addresses to those loaded from the database. $db_delivery_address = $db_order->getAddress('delivery'); $db_billing_address = $db_order->getAddress('billing'); $this->assertEqual($delivery_address, $db_delivery_address, 'Delivery address is equal to delivery address in database.'); $this->assertEqual($billing_address, $db_billing_address, 'Billing address is equal to billing address in database.'); return $order; }
/** * Displays the cart checkout page built of checkout panes from enabled modules. */ public function checkout() { $cart_config = $this->config('uc_cart.settings'); $items = $this->cartManager->get()->getContents(); if (count($items) == 0 || !$cart_config->get('checkout_enabled')) { return $this->redirect('uc_cart.cart'); } // Send anonymous users to login page when anonymous checkout is disabled. if ($this->currentUser()->isAnonymous() && !$cart_config->get('checkout_anonymous')) { drupal_set_message($this->t('You must login before you can proceed to checkout.')); if ($this->config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) { drupal_set_message($this->t('If you do not have an account yet, you should <a href=":url">register now</a>.', [':url' => Url::fromRoute('user.register', [], ['query' => drupal_get_destination()])->toString()])); } return $this->redirect('user.page', [], ['query' => drupal_get_destination()]); } // Load an order from the session, if available. if ($this->session->has('cart_order')) { $order = $this->loadOrder(); if ($order) { // Don't use an existing order if it has changed status or owner, or if // there has been no activity for 10 minutes (to prevent identity theft). if ($order->getStateId() != 'in_checkout' || $this->currentUser()->isAuthenticated() && $this->currentUser()->id() != $order->getOwnerId() || $order->getChangedTime() < REQUEST_TIME - CartInterface::CHECKOUT_TIMEOUT) { if ($order->getStateId() == 'in_checkout' && $order->getChangedTime() < REQUEST_TIME - CartInterface::CHECKOUT_TIMEOUT) { // Mark expired orders as abandoned. $order->setStatusId('abandoned')->save(); } unset($order); } } else { // Ghost session. $this->session->remove('cart_order'); drupal_set_message($this->t('Your session has expired or is no longer valid. Please review your order and try again.')); return $this->redirect('uc_cart.cart'); } } // Determine whether the form is being submitted or built for the first time. if (isset($_POST['form_id']) && $_POST['form_id'] == 'uc_cart_checkout_form') { // If this is a form submission, make sure the cart order is still valid. if (!isset($order)) { drupal_set_message($this->t('Your session has expired or is no longer valid. Please review your order and try again.')); return $this->redirect('uc_cart.cart'); } elseif ($this->session->has('uc_cart_order_rebuild')) { drupal_set_message($this->t('Your shopping cart contents have changed. Please review your order and try again.')); return $this->redirect('uc_cart.cart'); } } else { // Prepare the cart order. $rebuild = FALSE; if (!isset($order)) { // Create a new order if necessary. $order = Order::create(array('uid' => $this->currentUser()->id())); $order->save(); $this->session->set('cart_order', $order->id()); $rebuild = TRUE; } elseif ($this->session->has('uc_cart_order_rebuild')) { // Or, if the cart has changed, then remove old products and line items. $result = \Drupal::entityQuery('uc_order_product')->condition('order_id', $order->id())->execute(); if (!empty($result)) { $storage = $this->entityTypeManager()->getStorage('uc_order_product'); $entities = $storage->loadMultiple(array_keys($result)); $storage->delete($entities); } uc_order_delete_line_item($order->id(), TRUE); $rebuild = TRUE; } if ($rebuild) { // Copy the cart contents to the cart order. $order->products = array(); foreach ($items as $item) { $order->products[] = $item->toOrderProduct(); } $this->session->remove('uc_cart_order_rebuild'); } elseif (!uc_order_product_revive($order->products)) { drupal_set_message($this->t('Some of the products in this order are no longer available.'), 'error'); return $this->redirect('uc_cart.cart'); } } $min = $cart_config->get('minimum_subtotal'); if ($min > 0 && $order->getSubtotal() < $min) { drupal_set_message($this->t('The minimum order subtotal for checkout is @min.', ['@min' => uc_currency_format($min)]), 'error'); return $this->redirect('uc_cart.cart'); } // Trigger the "Customer starts checkout" hook and event. $this->moduleHandler()->invokeAll('uc_cart_checkout_start', array($order)); // rules_invoke_event('uc_cart_checkout_start', $order); return $this->formBuilder()->getForm('Drupal\\uc_cart\\Form\\CheckoutForm', $order); }
/** * React on INS messages from 2Checkout. * * @param \Symfony\Component\HttpFoundation\Request $request * The request of the page. */ public function notification(Request $request) { $values = $request->request; \Drupal::logger('uc_2checkout')->notice('Received 2Checkout notification with following data: @data', ['@data' => print_r($values->all(), TRUE)]); $module_config = $this->config('uc_2checkout.settings'); if ($values->has('message_type') && $values->has('md5_hash') && $values->has('message_id')) { // Validate the hash $secret_word = $module_config->get('secret_word'); $sid = $module_config->get('sid'); $twocheckout_order_id = $values->get('sale_id'); $twocheckout_invoice_id = $values->get('invoice_id'); $hash = strtoupper(md5($twocheckout_order_id . $sid . $twocheckout_invoice_id . $secret_word)); if ($hash != $values->get('md5_hash')) { \Drupal::logger('uc_2checkout')->notice('2Checkout notification #@num had a wrong hash.', ['@num' => $values->get('message_id')]); die('Hash Incorrect'); } $order_id = $values->get('vendor_order_id'); $order = Order::load($order_id); if ($values->get('message_type') == 'FRAUD_STATUS_CHANGED') { switch ($values->get('fraud_status')) { // @todo: I think this still needs a lot of work, I don't see anywhere that it // validates the INS against an order in the DB then changes order status if the // payment was successful, like PayPal IPN does ... case 'pass': break; case 'wait': break; case 'fail': // @todo uc_order_update_status($order_id, uc_order_state_default('canceled')); $order->setStatusId('canceled')->save(); uc_order_comment_save($order_id, 0, $this->t('Order have not passed 2Checkout fraud review.')); die('fraud'); break; } } elseif ($values->get('message_type') == 'REFUND_ISSUED') { // @todo uc_order_update_status($order_id, uc_order_state_default('canceled')); $order->setStatusId('canceled')->save(); uc_order_comment_save($order_id, 0, $this->t('Order have been refunded through 2Checkout.')); die('refund'); } } die('ok'); }
/** * Tests basic flatrate shipping quote functionality. */ public function testQuote() { // Create product and quotes. $product = $this->createProduct(); $quote1 = $this->createQuote(); $quote2 = $this->createQuote(array(), array('LABEL' => 'quote_conditions', 'PLUGIN' => 'and', 'REQUIRES' => array('rules'), 'USES VARIABLES' => array('order' => array('type' => 'uc_order', 'label' => 'Order')), 'AND' => array(array('data_is' => array('data' => array('order:delivery-address:country'), 'value' => 'US'))))); // Define strings to test for. $qty = mt_rand(2, 100); foreach ([$quote1, $quote2] as $quote) { $quote->amount = uc_currency_format($quote->base_rate + $quote->product_rate * $qty); $quote->option_text = $quote->label . ': ' . $quote->amount; $quote->total = uc_currency_format($product->price->value * $qty + $quote->base_rate + $quote->product_rate * $qty); } // Add product to cart, update qty, and go to checkout page. $this->addToCart($product); $this->drupalPostForm('cart', array('items[0][qty]' => $qty), t('Checkout')); $this->assertText($quote1->option_text, 'The default quote option is available'); $this->assertText($quote2->option_text, 'The second quote option is available'); $this->assertText($quote1->total, 'Order total includes the default quote.'); // Select a different quote and ensure the total updates correctly. Currently, we have to do this // by examining the ajax return value directly (rather than the page contents) because drupalPostAjaxForm() can // only handle replacements via the 'wrapper' property, and the ajax callback may use a command with a selector. $edit = array('panes[quotes][quotes][quote_option]' => 'flatrate_2---0'); $edit = $this->populateCheckoutForm($edit); $result = $this->ucPostAjax(NULL, $edit, $edit); $this->assertText($quote2->total, 'The order total includes the selected quote.'); // @todo Re-enable when shipping quote conditions are available. // Switch to a different country and ensure the ajax updates the page correctly. // $edit['panes[delivery][country]'] = 'CA'; // $result = $this->ucPostAjax(NULL, $edit, 'panes[delivery][country]'); // $this->assertText($quote1->option_text, 'The default quote is still available after changing the country.'); // $this->assertNoText($quote2->option_text, 'The second quote is no longer available after changing the country.'); // $this->assertText($quote1->total, 'The total includes the default quote.'); // Proceed to review page and ensure the correct quote is present. $edit['panes[quotes][quotes][quote_option]'] = 'flatrate_1---0'; $edit = $this->populateCheckoutForm($edit); $this->drupalPostForm(NULL, $edit, t('Review order')); $this->assertRaw(t('Your order is almost complete.')); $this->assertText($quote1->total, 'The total is correct on the order review page.'); // Submit the review order page. $this->drupalPostForm(NULL, [], t('Submit order')); $order_ids = \Drupal::entityQuery('uc_order')->condition('delivery_first_name', $edit['panes[delivery][first_name]'])->execute(); $order_id = reset($order_ids); if ($order_id) { $order = \Drupal\uc_order\Entity\Order::load($order_id); foreach ($order->line_items as $line) { if ($line['type'] == 'shipping') { break; } } // Verify line item is correct. $this->assertEqual($line['type'], 'shipping', 'The shipping line item was saved to the order.'); $this->assertEqual($quote1->amount, uc_currency_format($line['amount']), 'Stored shipping line item has the correct amount.'); // Verify order total is correct on order-view form. $this->drupalGet('admin/store/orders/' . $order_id); $this->assertText($quote1->total, 'The total is correct on the order admin view page.'); // Verify shipping line item is correct on order edit form. $this->drupalGet('admin/store/orders/' . $order_id . '/edit'); $this->assertFieldByName('line_items[' . $line['line_item_id'] . '][title]', $quote1->label, 'Found the correct shipping line item title.'); $this->assertFieldByName('line_items[' . $line['line_item_id'] . '][amount]', substr($quote1->amount, 1), 'Found the correct shipping line item title.'); // Verify that the "get quotes" button works as expected. $result = $this->ucPostAjax('admin/store/orders/' . $order_id . '/edit', [], ['op' => t('Get shipping quotes')]); $this->assertText($quote1->option_text, 'The default quote is available on the order-edit page.'); // @todo Change to assertNoText when shipping quote conditions are available. $this->assertText($quote2->option_text, 'The second quote is available on the order-edit page.'); } else { $this->fail('No order was created.'); } }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { switch ($form_state->getValue('customer_type')) { case 'search': $uid = $form_state->getValue(['customer', 'uid']); break; case 'create': // Create new account. $email = trim($form_state->getValue(['customer', 'email'])); $fields = array('name' => uc_store_email_to_username($email), 'mail' => $email, 'pass' => user_password(), 'status' => $this->config('uc_cart.settings')->get('new_customer_status_active') ? 1 : 0); $account = \Drupal\user\Entity\User::create($fields); $account->save(); $uid = $account->id(); if ($form_state->getValue(['customer', 'sendmail'])) { // Manually set the password so it appears in the e-mail. $account->password = $fields['pass']; \Drupal::service('plugin.manager.mail')->mail('user', 'register_admin_created', $email, uc_store_mail_recipient_langcode($email), array('account' => $account), uc_store_email_from()); drupal_set_message(t('A welcome message has been e-mailed to the new user.')); } break; default: $uid = 0; } $order = \Drupal\uc_order\Entity\Order::create(array('uid' => $uid, 'order_status' => uc_order_state_default('post_checkout'))); $order->save(); uc_order_comment_save($order->id(), \Drupal::currentUser()->id(), t('Order created by the administration.'), 'admin'); $form_state->setRedirect('entity.uc_order.edit_form', ['uc_order' => $order->id()]); }
public function testPackagesUI() { $this->drupalLogin($this->adminUser); $method = $this->createPaymentMethod('other'); // Process an anonymous, shippable order. $order = Order::create(['uid' => 0, 'primary_email' => $this->randomString() . '@example.org', 'payment_method' => $method['id']]); // Add three more products to use for our tests. $products = array(); for ($i = 1; $i <= 4; $i++) { $product = $this->createProduct(array('uid' => $this->adminUser->id(), 'promote' => 0)); $order->products[$i] = OrderProduct::create(array('nid' => $product->nid->target_id, 'title' => $product->title->value, 'model' => $product->model, 'qty' => 1, 'cost' => $product->cost->value, 'price' => $product->price->value, 'weight' => $product->weight, 'data' => [])); $order->products[$i]->data->shippable = 1; } $order->save(); $order = Order::load($order->id()); uc_payment_enter($order->id(), $method['id'], $order->getTotal()); // Order with 4 products shippable products. (where do we test not-shippable?) // Check all, make one package, verify we're on packages page with only one packge. // Try create package link, should see there are no products message. // Delete package. // Check all, make shipment, verify we're on packages page with N packages. // Delete packages. // How does Sep work? how does making 2 packages out of 4 products work? // Check all, cancel, verify we're on order page. // After packages made and check for # (check make one and make shipment, use sep. as well) // Can use edit/delete actions to package then start over with the same order. // and check for full table at /packages and check for action on /packages page, // goto shipments tab and look for No shipments have been made for this order. as well as a list of all the packages. // // Test presence and operation of package operation on order admin View. // $this->drupalGet('admin/store/orders/view'); $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/packages'); // Test action. $this->clickLink(t('Package')); $this->assertResponse(200); $this->assertText('This order\'s products have not been organized into packages.', 'Package action found.'); // Now package the products in this order. $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); // First time through we'll be verbose - skip this on subsequent tests. foreach ($order->products as $sequence => $item) { $this->assertText($item->title->value, 'Product title found.'); $this->assertText($item->model->value, 'Product SKU found.'); $this->assertFieldByName('shipping_types[small_package][table][' . $sequence . '][checked]', 0, 'Product is available for packaging.'); } // Select all products and test the "Cancel" button. $this->drupalPostForm(NULL, array('shipping_types[small_package][table][1][checked]' => 1, 'shipping_types[small_package][table][2][checked]' => 1, 'shipping_types[small_package][table][3][checked]' => 1, 'shipping_types[small_package][table][4][checked]' => 1), t('Cancel')); // Go back to Packages tab and try something else. $this->assertUrl('admin/store/orders/' . $order->id()); $this->clickLink(t('Packages')); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); $this->assertText('This order\'s products have not been organized into packages.', 'Package action found.'); // Now test the "Create one package" button without selecting anything. $this->drupalPostForm(NULL, array(), t('Create one package')); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); $this->assertText('Packages must contain at least one product.', 'Validation that there must be products in a package.'); // Now test the "Create one package" button with all products selected. $this->drupalPostForm(NULL, array('shipping_types[small_package][table][1][checked]' => 1, 'shipping_types[small_package][table][2][checked]' => 1, 'shipping_types[small_package][table][3][checked]' => 1, 'shipping_types[small_package][table][4][checked]' => 1), t('Create one package')); // Check that we're now on the package list page. $this->assertUrl('admin/store/orders/' . $order->id() . '/packages'); foreach ($order->products as $sequence => $item) { $this->assertText($item->qty->value . ' x ' . $item->model->value, 'Product quantity x SKU found.'); } // The "Create packages" local action should now be available too. $this->assertLink(t('Create packages')); $this->clickLink(t('Create packages')); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); // But we've already packaged everything... $this->assertText('There are no products available for this type of package.', 'Create packages local action found.'); // // Test "Ship", "Edit", and "Delete" operations for this package. // // First "Ship". $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); $this->assertLink(t('Ship')); $this->clickLink(t('Ship')); $this->assertUrl('admin/store/orders/' . $order->id() . '/shipments/new?pkgs=1'); foreach ($order->products as $sequence => $item) { $this->assertText($item->qty->value . ' x ' . $item->model->value, 'Product quantity x SKU found.'); } // Second, "Edit". $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); // (Use Href to distinguish Edit operation from Edit tab.) $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/packages/1/edit'); $this->drupalGet('admin/store/orders/' . $order->id() . '/packages/1/edit'); // We're editing the package we already made, so all the // products should be checked. foreach ($order->products as $sequence => $item) { $this->assertFieldByName('products[' . $sequence . '][checked]', 1, 'Product is available for packaging.'); } // Third, "Delete". $this->drupalGet('admin/store/orders/' . $order->id() . '/packages'); $this->assertLink(t('Delete')); $this->clickLink(t('Delete')); // Delete takes us to confirm page. $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/1/delete'); $this->assertText('The products it contains will be available for repackaging.', 'Deletion confirm question found.'); // "Cancel" returns to the package list page. $this->clickLink(t('Cancel')); $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/packages'); // Again with the "Delete". $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete')); // Delete returns to new packages page with all packages unchecked. $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); $this->assertText('Package 1 has been deleted.', 'Package deleted message found.'); foreach ($order->products as $sequence => $item) { $this->assertFieldByName('shipping_types[small_package][table][' . $sequence . '][checked]', 0, 'Product is available for packaging.'); } // Back to no packages. Now test making more than one package. // Now test the "Create one package" button with all products selected. $this->drupalPostForm(NULL, array('shipping_types[small_package][table][1][checked]' => 1, 'shipping_types[small_package][table][2][checked]' => 1), t('Create one package')); // Check that we're now on the package list page. $this->assertUrl('admin/store/orders/' . $order->id() . '/packages'); $this->assertText($order->products[1]->qty->value . ' x ' . $order->products[1]->model->value, 'Product quantity x SKU found.'); $this->assertText($order->products[2]->qty->value . ' x ' . $order->products[2]->model->value, 'Product quantity x SKU found.'); $this->assertNoText($order->products[3]->qty->value . ' x ' . $order->products[3]->model->value, 'Product quantity x SKU not found.'); $this->assertNoText($order->products[4]->qty->value . ' x ' . $order->products[4]->model->value, 'Product quantity x SKU not found.'); // Use "Create packages" to create a second package. $this->assertLink(t('Create packages')); $this->clickLink(t('Create packages')); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); $this->assertNoText($order->products[1]->model->value, 'Product SKU not found.'); $this->assertNoText($order->products[2]->model->value, 'Product SKU not found.'); $this->assertText($order->products[3]->model->value, 'Product SKU found.'); $this->assertText($order->products[4]->model->value, 'Product SKU found.'); $this->drupalPostForm(NULL, array('shipping_types[small_package][table][3][checked]' => 1, 'shipping_types[small_package][table][4][checked]' => 1), t('Create one package')); $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/packages'); foreach ($order->products as $sequence => $item) { $this->assertText($item->qty->value . ' x ' . $item->model->value, 'Product quantity x SKU found.'); } // How do we test for two packages? Look for two "Ship" links $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/shipments/new?pkgs=2'); $this->assertLinkByHref('admin/store/orders/' . $order->id() . '/shipments/new?pkgs=3'); // Now delete both packages. $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete')); $this->assertText('Package 2 has been deleted.', 'Package deleted message found.'); // There's still one left to delete... $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete')); $this->assertUrl('admin/store/orders/' . $order->id() . '/packages/new'); $this->assertText('Package 3 has been deleted.', 'Package deleted message found.'); // Back to no packages. Now test "Make packages" button. $this->drupalPostForm(NULL, array('shipping_types[small_package][table][1][checked]' => 1, 'shipping_types[small_package][table][2][checked]' => 1, 'shipping_types[small_package][table][3][checked]' => 1, 'shipping_types[small_package][table][4][checked]' => 1), t('Make packages')); // Check that we're now on the package list page. $this->assertUrl('admin/store/orders/' . $order->id() . '/packages'); foreach ($order->products as $sequence => $item) { $this->assertText($item->qty->value . ' x ' . $item->model->value, 'Product quantity x SKU found.'); } }
/** * {@inheritdoc} */ public function render(ResultRow $values) { $order = Order::load($this->getValue($values)); return uc_order_actions($order, TRUE); }
/** * Tests for Other payment method. */ public function testOther() { $this->drupalGet('admin/store/config/payment'); $this->assertText('Other', 'Other payment method found.'); $this->assertFieldByName('methods[other][status]', 0, 'Other payment method is disabled by default.'); $edit = array('methods[other][status]' => 1, 'methods[other][weight]' => -10); $this->drupalPostForm(NULL, $edit, 'Save configuration'); // Test checkout page $this->drupalGet('cart/checkout'); $this->assertFieldByName('panes[payment][payment_method]', 'other', 'Other payment method is selected at checkout.'); // Test review order page $this->drupalPostForm(NULL, array(), 'Review order'); $this->assertText('Other', 'Other payment method found on review page.'); $this->drupalPostForm(NULL, array(), 'Submit order'); // Test user order view $order = \Drupal\uc_order\Entity\Order::load(1); $this->assertEqual($order->getPaymentMethodId(), 'other', 'Order has other payment method.'); $this->drupalGet('user/' . $order->getUserId() . '/orders/' . $order->id()); $this->assertText('Method: Other', 'Other payment method displayed.'); // Test admin order view $this->drupalGet('admin/store/orders/' . $order->id()); $this->assertText('Method: Other', 'Other payment method displayed.'); $this->drupalGet('admin/store/orders/' . $order->id() . '/edit'); $this->assertFieldByName('payment_method', 'other', 'Other payment method is selected in the order edit form.'); $edit = array('payment_details[description]' => $this->randomString()); $this->drupalPostForm(NULL, array(), 'Save changes'); // @todo: Test storage of payment details. }