diff --git a/CRM/Core/Payment/AuthorizeNet.php b/CRM/Core/Payment/AuthorizeNet.php
index 8a017838f829c2ca63e84f540a0d3abc783e9241..26b0edc6898dc76b2ba987be35e088f1025534eb 100644
--- a/CRM/Core/Payment/AuthorizeNet.php
+++ b/CRM/Core/Payment/AuthorizeNet.php
@@ -113,7 +113,9 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (!defined('CURLOPT_SSLCERT')) {
-      return self::error(9001, 'Authorize.Net requires curl with SSL support');
+      // Note that guzzle doesn't necessarily require CURL, although it prefers it. But we should leave this error
+      // here unless someone suggests it is not required since it's likely helpful.
+      throw new PaymentProcessorException('Authorize.Net requires curl with SSL support', 9001);
     }
 
     /*
@@ -158,24 +160,13 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
       return self::error(9004, 'It appears that this transaction is a duplicate.  Have you already submitted the form once?  If so there may have been a connection problem.  Check your email for a receipt from Authorize.net.  If you do not receive a receipt within 2 hours you can try your transaction again.  If you continue to have problems please contact the site administrator.');
     }
 
-    $submit = curl_init($this->_paymentProcessor['url_site']);
-
-    if (!$submit) {
-      return self::error(9002, 'Could not initiate connection to payment gateway');
-    }
-
-    curl_setopt($submit, CURLOPT_POST, TRUE);
-    curl_setopt($submit, CURLOPT_RETURNTRANSFER, TRUE);
-    curl_setopt($submit, CURLOPT_POSTFIELDS, implode('&', $postFields));
-    curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, Civi::settings()->get('verifySSL'));
-
-    $response = curl_exec($submit);
-
-    if (!$response) {
-      return self::error(curl_errno($submit), curl_error($submit));
-    }
-
-    curl_close($submit);
+    $response = (string) $this->getGuzzleClient()->post($this->_paymentProcessor['url_site'], [
+      'body' => implode('&', $postFields),
+      'curl' => [
+        CURLOPT_RETURNTRANSFER => TRUE,
+        CURLOPT_SSL_VERIFYPEER => Civi::settings()->get('verifySSL'),
+      ],
+    ])->getBody();
 
     $response_fields = $this->explode_csv($response);
 
diff --git a/tests/phpunit/CRM/Core/Payment/AuthorizeNetTest.php b/tests/phpunit/CRM/Core/Payment/AuthorizeNetTest.php
index 63b4c4bd2cc7dc4b18d50546b99b1ed9194baec9..8d6d21d6e1c51f3231a5a9228914db6ae6509001 100644
--- a/tests/phpunit/CRM/Core/Payment/AuthorizeNetTest.php
+++ b/tests/phpunit/CRM/Core/Payment/AuthorizeNetTest.php
@@ -38,6 +38,39 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     $this->quickCleanUpFinancialEntities();
   }
 
+  /**
+   * Test doing a one-off payment.
+   *
+   * @throws \Civi\Payment\Exception\PaymentProcessorException
+   */
+  public function testSinglePayment() {
+    $this->createMockHandler([$this->getExpectedSinglePaymentResponse()]);
+    $this->setUpClientWithHistoryContainer();
+    $this->processor->setGuzzleClient($this->getGuzzleClient());
+    $params = $this->getBillingParams();
+    $params['amount'] = 5.24;
+    $this->processor->doPayment($params);
+    $this->assertEquals($this->getExpectedSinglePaymentRequest(), $this->getRequestBodies()[0]);
+  }
+
+  /**
+   * Get the expected response from Authorize.net.
+   *
+   * @return string
+   */
+  public function getExpectedSinglePaymentResponse() {
+    return '"1","1","1","(TESTMODE) This transaction has been approved.","000000","P","0","","","5.24","CC","auth_capture","","John","O'Connor","","","","","","","","","","","","","","","","","","","","","","","",""';
+  }
+
+  /**
+   *  Get the expected request from Authorize.net.
+   *
+   * @return string
+   */
+  public function getExpectedSinglePaymentRequest() {
+    return 'x_login=4y5BfuW7jm&x_tran_key=4cAmW927n8uLf5J8&x_email_customer=&x_first_name=John&x_last_name=O%27Connor&x_address=&x_city=&x_state=&x_zip=&x_country=&x_customer_ip=&x_email=&x_invoice_num=&x_amount=5.24&x_currency_code=&x_description=&x_cust_id=&x_relay_response=FALSE&x_delim_data=TRUE&x_delim_char=%2C&x_encap_char=%22&x_card_num=4444333322221111&x_card_code=123&x_exp_date=10%2F2022&x_test_request=TRUE';
+  }
+
   /**
    * Create a single post dated payment as a recurring transaction.
    *
@@ -48,7 +81,7 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     $this->setUpClientWithHistoryContainer();
     $this->processor->setGuzzleClient($this->getGuzzleClient());
     $firstName = 'John';
-    $lastName = 'Smith';
+    $lastName = "O\'Connor";
     $nameParams = ['first_name' => 'John', 'last_name' => $lastName];
     $contactId = $this->individualCreate($nameParams);
 
@@ -82,24 +115,11 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'contribution_status_id' => 2,
     ]);
 
-    $params = [
+    $billingParams = $this->getBillingParams();
+
+    $params = array_merge($billingParams, [
       'qfKey' => '08ed21c7ca00a1f7d32fff2488596ef7_4454',
       'hidden_CreditCard' => 1,
-      'billing_first_name' => $firstName,
-      'billing_middle_name' => '',
-      'billing_last_name' => $lastName,
-      'billing_street_address-5' => '8 Hobbitton Road',
-      'billing_city-5' => 'The Shire',
-      'billing_state_province_id-5' => 1012,
-      'billing_postal_code-5' => 5010,
-      'billing_country_id-5' => 1228,
-      'credit_card_number' => '4444333322221111',
-      'cvv2' => 123,
-      'credit_card_exp_date' => [
-        'M' => 9,
-        'Y' => 2025,
-      ],
-      'credit_card_type' => 'Visa',
       'is_recur' => 1,
       'frequency_interval' => 1,
       'frequency_unit' => 'month',
@@ -147,12 +167,12 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'contributionType_name' => 'My precious',
       'contributionType_accounting_code' => '',
       'contributionPageID' => '',
-      'email' => "{$firstName}.{$lastName}@example.com",
+      'email' => 'john.smith@example.com',
       'contactID' => $contactId,
       'contributionID' => $contribution['id'],
       'contributionTypeID' => $this->_financialTypeId,
       'contributionRecurID' => $recur['id'],
-    ];
+    ]);
 
     // turn verifySSL off
     Civi::settings()->set('verifySSL', '0');
@@ -193,7 +213,7 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     $start_date = date('Ymd', strtotime('+ 1 week'));
 
     $firstName = 'John';
-    $lastName = 'Smith';
+    $lastName = "O'Connor";
     $nameParams = ['first_name' => $firstName, 'last_name' => $lastName];
     $contactId = $this->individualCreate($nameParams);
 
@@ -294,7 +314,7 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'postal_code' => 5010,
       'country' => 'US',
       'contributionPageID' => '',
-      'email' => "{$firstName}.{$lastName}@example.com",
+      'email' => 'john.smith@example.com',
       'contactID' => $contactId,
       'contributionID' => $contribution['id'],
       'contributionRecurID' => $recur['id'],
@@ -366,11 +386,11 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
         </order>
        <customer>
       <id>' . $contactID . '</id>
-      <email>John.Smith@example.com</email>
+      <email>john.smith@example.com</email>
     </customer>
     <billTo>
       <firstName>John</firstName>
-      <lastName>Smith</lastName>
+      <lastName>O\'Connor</lastName>
       <address>8 Hobbiton Road</address>
       <city>The Shire</city>
       <state>IL</state>
@@ -391,4 +411,31 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     return '<?xml version="1.0" encoding="utf-8"?><ARBCreateSubscriptionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><refId>8d468ca1b1dd5c2b56c7</refId><messages><resultCode>Ok</resultCode><message><code>I00001</code><text>Successful.</text></message></messages><subscriptionId>6632052</subscriptionId><profile><customerProfileId>1512023280</customerProfileId><customerPaymentProfileId>1512027350</customerPaymentProfileId></profile></ARBCreateSubscriptionResponse>';
   }
 
+  /**
+   * Get some basic billing parameters.
+   *
+   * @return array
+   */
+  protected function getBillingParams(): array {
+    return [
+      'billing_first_name' => 'John',
+      'billing_middle_name' => '',
+      'billing_last_name' => "O'Connor",
+      'billing_street_address-5' => '8 Hobbitton Road',
+      'billing_city-5' => 'The Shire',
+      'billing_state_province_id-5' => 1012,
+      'billing_postal_code-5' => 5010,
+      'billing_country_id-5' => 1228,
+      'credit_card_number' => '4444333322221111',
+      'cvv2' => 123,
+      'credit_card_exp_date' => [
+        'M' => 9,
+        'Y' => 2025,
+      ],
+      'credit_card_type' => 'Visa',
+      'year' => 2022,
+      'month' => 10,
+    ];
+  }
+
 }