diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php
index 75afd52626f1886e39dab59f034ce31dba7b4930..dabaa52f5ac9f3aa46c27d1234428fd76a7b8bdc 100644
--- a/CRM/Contribute/BAO/Contribution.php
+++ b/CRM/Contribute/BAO/Contribution.php
@@ -4481,10 +4481,6 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
     }
     $changeDate = CRM_Utils_Array::value('trxn_date', $input, date('YmdHis'));
 
-    if (empty($contributionParams['receive_date']) && $changeDate) {
-      $contributionParams['receive_date'] = $changeDate;
-    }
-
     self::repeatTransaction($contribution, $input, $contributionParams, $paymentProcessorId);
     $contributionParams['financial_type_id'] = $contribution->financial_type_id;
 
diff --git a/CRM/Contribute/Form/Task/PDF.php b/CRM/Contribute/Form/Task/PDF.php
index 76dac1989fb10104e73d07fed177da16684294bb..7552bf9222908043946b581a0532337cf0e741c7 100644
--- a/CRM/Contribute/Form/Task/PDF.php
+++ b/CRM/Contribute/Form/Task/PDF.php
@@ -253,7 +253,7 @@ AND    {$this->_componentClause}";
 
     $pdfElements['contribIDs'] = implode(',', $contribIds);
 
-    $pdfElements['details'] = CRM_Contribute_Form_Task_Status::getDetails($pdfElements['contribIDs']);
+    $pdfElements['details'] = self::getDetails($pdfElements['contribIDs']);
 
     $pdfElements['baseIPN'] = new CRM_Core_Payment_BaseIPN();
 
@@ -295,4 +295,47 @@ AND    {$this->_componentClause}";
     return $pdfElements;
   }
 
+  /**
+   * @param string $contributionIDs
+   *
+   * @return array
+   */
+  private static function getDetails($contributionIDs) {
+    if (empty($contributionIDs)) {
+      return [];
+    }
+    $query = "
+SELECT    c.id              as contribution_id,
+          c.contact_id      as contact_id     ,
+          mp.membership_id  as membership_id  ,
+          pp.participant_id as participant_id ,
+          p.event_id        as event_id
+FROM      civicrm_contribution c
+LEFT JOIN civicrm_membership_payment  mp ON mp.contribution_id = c.id
+LEFT JOIN civicrm_participant_payment pp ON pp.contribution_id = c.id
+LEFT JOIN civicrm_participant         p  ON pp.participant_id  = p.id
+WHERE     c.id IN ( $contributionIDs )";
+
+    $rows = [];
+    $dao = CRM_Core_DAO::executeQuery($query);
+
+    while ($dao->fetch()) {
+      $rows[$dao->contribution_id]['component'] = $dao->participant_id ? 'event' : 'contribute';
+      $rows[$dao->contribution_id]['contact'] = $dao->contact_id;
+      if ($dao->membership_id) {
+        if (!array_key_exists('membership', $rows[$dao->contribution_id])) {
+          $rows[$dao->contribution_id]['membership'] = [];
+        }
+        $rows[$dao->contribution_id]['membership'][] = $dao->membership_id;
+      }
+      if ($dao->participant_id) {
+        $rows[$dao->contribution_id]['participant'] = $dao->participant_id;
+      }
+      if ($dao->event_id) {
+        $rows[$dao->contribution_id]['event'] = $dao->event_id;
+      }
+    }
+    return $rows;
+  }
+
 }
diff --git a/CRM/Contribute/Form/Task/Status.php b/CRM/Contribute/Form/Task/Status.php
index e3c2a6e7daa1b769f2e689ddc4efc3b55755c9dc..b501327a88f5757e27a1e0f25b5f9eab757cd832 100644
--- a/CRM/Contribute/Form/Task/Status.php
+++ b/CRM/Contribute/Form/Task/Status.php
@@ -68,21 +68,6 @@ AND    {$this->_componentClause}";
    * Build the form object.
    */
   public function buildQuickForm() {
-    $status = CRM_Contribute_BAO_Contribution_Utils::getContributionStatuses(
-      'contribution', $this->_contributionIds[0]
-    );
-    $byName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
-    // FIXME: if it's invalid to transition from Pending to
-    // In Progress or Overdue, we should move that logic to
-    // CRM_Contribute_BAO_Contribution_Utils::getContributionStatuses.
-    foreach (['Pending', 'In Progress', 'Overdue'] as $suppress) {
-      unset($status[CRM_Utils_Array::key($suppress, $byName)]);
-    }
-    $this->add('select', 'contribution_status_id',
-      ts('Contribution Status'),
-      $status,
-      TRUE
-    );
     $this->add('checkbox', 'is_email_receipt', ts('Send e-mail receipt'));
     $this->setDefaults(['is_email_receipt' => 1]);
 
@@ -198,7 +183,7 @@ AND    co.id IN ( $contribIDs )";
     // submit the form with values.
     self::processForm($this, $params);
 
-    CRM_Core_Session::setStatus(ts('Contribution status has been updated for selected record(s).'), ts('Status Updated'), 'success');
+    CRM_Core_Session::setStatus(ts('Payments have been recorded for selected record(s).'), ts('Payments recorded'), 'success');
   }
 
   /**
@@ -212,124 +197,26 @@ AND    co.id IN ( $contribIDs )";
    * @throws \Exception
    */
   public static function processForm($form, $params) {
-    $statusID = $params['contribution_status_id'] ?? NULL;
-    $baseIPN = new CRM_Core_Payment_BaseIPN();
-
-    // get the missing pieces for each contribution
-    $contribIDs = implode(',', $form->_contributionIds);
-    $details = self::getDetails($contribIDs);
-    $template = CRM_Core_Smarty::singleton();
-
-    // for each contribution id, we just call the baseIPN stuff
     foreach ($form->_rows as $row) {
-      $input = $ids = $objects = [];
-      $input['component'] = $details[$row['contribution_id']]['component'];
-
-      $ids['contact'] = $row['contact_id'];
-      $ids['contribution'] = $row['contribution_id'];
-      $ids['contributionRecur'] = NULL;
-      $ids['contributionPage'] = NULL;
-      $ids['membership'] = $details[$row['contribution_id']]['membership'] ?? NULL;
-      $ids['participant'] = $details[$row['contribution_id']]['participant'] ?? NULL;
-      $ids['event'] = $details[$row['contribution_id']]['event'] ?? NULL;
-
-      if (!$baseIPN->validateData($input, $ids, $objects, FALSE)) {
-        CRM_Core_Error::statusBounce('Supplied data was not able to be validated');
-      }
-
-      $contribution = &$objects['contribution'];
-
-      $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL,
-        'name'
-      );
-
-      if ($statusID == array_search('Cancelled', $contributionStatuses)) {
-        $transaction = new CRM_Core_Transaction();
-        $baseIPN->cancelled($objects, $transaction);
-        $transaction->commit();
-        continue;
-      }
-      elseif ($statusID == array_search('Failed', $contributionStatuses)) {
-        $transaction = new CRM_Core_Transaction();
-        $baseIPN->failed($objects, $transaction);
-        $transaction->commit();
-        continue;
-      }
-
-      // status is not pending
-      if ($contribution->contribution_status_id != array_search('Pending',
-          $contributionStatuses
-        )
-      ) {
-        continue;
-      }
-
-      // set some fake input values so we can reuse IPN code
-      $input['amount'] = $contribution->total_amount;
-      $input['is_test'] = $contribution->is_test;
-      $input['fee_amount'] = $params["fee_amount_{$row['contribution_id']}"];
-      $input['check_number'] = $params["check_number_{$row['contribution_id']}"];
-      $input['payment_instrument_id'] = $params["payment_instrument_id_{$row['contribution_id']}"];
-      $input['net_amount'] = $contribution->total_amount - $input['fee_amount'];
-
-      if (!empty($params["trxn_id_{$row['contribution_id']}"])) {
-        $input['trxn_id'] = trim($params["trxn_id_{$row['contribution_id']}"]);
-      }
-      else {
-        $input['trxn_id'] = $contribution->invoice_id;
-      }
-      $input['trxn_date'] = $params["trxn_date_{$row['contribution_id']}"] . ' ' . date('H:i:s');
-      $input['is_email_receipt'] = !empty($params['is_email_receipt']);
-
-      // @todo calling CRM_Contribute_BAO_Contribution::completeOrder like this is a pattern in it's last gasps. Call contribute.completetransaction api.
-      CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects);
-
-      // reset template values before processing next transactions
-      $template->clearTemplateVars();
-    }
-  }
-
-  /**
-   * @param string $contributionIDs
-   *
-   * @return array
-   */
-  public static function &getDetails($contributionIDs) {
-    if (empty($contributionIDs)) {
-      return [];
-    }
-    $query = "
-SELECT    c.id              as contribution_id,
-          c.contact_id      as contact_id     ,
-          mp.membership_id  as membership_id  ,
-          pp.participant_id as participant_id ,
-          p.event_id        as event_id
-FROM      civicrm_contribution c
-LEFT JOIN civicrm_membership_payment  mp ON mp.contribution_id = c.id
-LEFT JOIN civicrm_participant_payment pp ON pp.contribution_id = c.id
-LEFT JOIN civicrm_participant         p  ON pp.participant_id  = p.id
-WHERE     c.id IN ( $contributionIDs )";
-
-    $rows = [];
-    $dao = CRM_Core_DAO::executeQuery($query);
-
-    while ($dao->fetch()) {
-      $rows[$dao->contribution_id]['component'] = $dao->participant_id ? 'event' : 'contribute';
-      $rows[$dao->contribution_id]['contact'] = $dao->contact_id;
-      if ($dao->membership_id) {
-        if (!array_key_exists('membership', $rows[$dao->contribution_id])) {
-          $rows[$dao->contribution_id]['membership'] = [];
-        }
-        $rows[$dao->contribution_id]['membership'][] = $dao->membership_id;
-      }
-      if ($dao->participant_id) {
-        $rows[$dao->contribution_id]['participant'] = $dao->participant_id;
-      }
-      if ($dao->event_id) {
-        $rows[$dao->contribution_id]['event'] = $dao->event_id;
-      }
+      $contribData = civicrm_api3('Contribution', 'getSingle', ['id' => $row['contribution_id']]);
+      $trxnParams = [
+        'contribution_id' => $row['contribution_id'],
+        // We are safe assuming that payments will be for the total amount of
+        // the contribution because the contributions must be in "Pending"
+        // status.
+        'total_amount' => $contribData['total_amount'],
+        'fee_amount' => $params["fee_amount_{$row['contribution_id']}"],
+        'check_number' => $params["check_number_{$row['contribution_id']}"],
+        'payment_instrument_id' => $params["payment_instrument_id_{$row['contribution_id']}"],
+        'net_amount' => $contribData['total_amount'] - $params["fee_amount_{$row['contribution_id']}"],
+        // Not sure why to default to invoice_id, but that's what the form has
+        // been doing historically
+        'trxn_id' => $params["trxn_id_{$row['contribution_id']}"] ?? $contribData['invoice_id'],
+        'trxn_date' => $params["trxn_date_{$row['contribution_id']}"] ?? 'now',
+        'is_send_contribution_notification' => !empty($params['is_email_receipt']),
+      ];
+      $result = civicrm_api3('Payment', 'create', $trxnParams);
     }
-    return $rows;
   }
 
 }
diff --git a/CRM/Contribute/Task.php b/CRM/Contribute/Task.php
index 9a88cfc6d51ad802e97268955d6a8e6e82d02a0b..24feae8a8797bf4ffe93389c0a468782a6e46544 100644
--- a/CRM/Contribute/Task.php
+++ b/CRM/Contribute/Task.php
@@ -81,7 +81,7 @@ class CRM_Contribute_Task extends CRM_Core_Task {
           'result' => TRUE,
         ],
         self::UPDATE_STATUS => [
-          'title' => ts('Update pending contribution status'),
+          'title' => ts('Record payments for contributions'),
           'class' => 'CRM_Contribute_Form_Task_Status',
           'result' => TRUE,
         ],
diff --git a/api/v3/Contribution.php b/api/v3/Contribution.php
index bbe016918144e5c0ad12852764d0970b6c4ff544..f80cd79d2944a2cb4d4117eef601dc50c7e831b2 100644
--- a/api/v3/Contribution.php
+++ b/api/v3/Contribution.php
@@ -488,7 +488,8 @@ function civicrm_api3_contribution_completetransaction($params) {
   elseif ($contribution->contribution_status_id == CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed')) {
     throw new API_Exception(ts('Contribution already completed'), 'contribution_completed');
   }
-  $input['trxn_id'] = !empty($params['trxn_id']) ? $params['trxn_id'] : $contribution->trxn_id;
+  $input['trxn_id'] = $params['trxn_id'] ?? $contribution->trxn_id;
+
   if (!empty($params['fee_amount'])) {
     $input['fee_amount'] = $params['fee_amount'];
   }
diff --git a/templates/CRM/Contribute/Form/Task/Status.tpl b/templates/CRM/Contribute/Form/Task/Status.tpl
index 635c4890d754714b33b4f0cd98b697a7a999e0e6..9d16b90aeb7f2741d9e6b1c8932c838042a6ef8d 100644
--- a/templates/CRM/Contribute/Form/Task/Status.tpl
+++ b/templates/CRM/Contribute/Form/Task/Status.tpl
@@ -8,50 +8,49 @@
  +--------------------------------------------------------------------+
 *}
 <div class="form-item crm-block crm-form-block crm-contribution-form-block">
-<div class="help">
-    {ts}Use this form to record received payments for 'pay later' online contributions, membership signups and event registrations. You can use the Transaction ID field to record account+check number, bank transfer identifier, or other unique payment identifier.{/ts}
-</div>
-<fieldset>
-    <legend>{ts}Update Contribution Status{/ts}</legend>
-     <table class="form-layout-compressed">
-     <tr class="crm-contribution-form-block-contribution_status_id"><td class="label">{$form.contribution_status_id.label}</td><td class="html-adjust">{$form.contribution_status_id.html}<br />
-            <span class="description">{ts}Assign the selected status to all contributions listed below.{/ts}</td></tr>
-       <tr class="crm-contribution-form-block-is_email_receipt"><td class="label">{$form.is_email_receipt.label}</td>
-         <td class="html-adjust">{$form.is_email_receipt.html}<br />
-           <span class="description">{ts}When checked CiviCRM will send an e-mail receipt to the donor. Leave unchecked when you don't want to send an e-mail.{/ts}
-         </td>
-       </tr>
-     </table>
-<table>
-<tr class="columnheader">
-    <th>{ts}Name{/ts}</th>
-    <th class="right">{ts}Amount{/ts}&nbsp;&nbsp;</th>
-    <th>{ts}Source{/ts}</th>
-    <th>{ts}Fee Amount{/ts}</th>
-    <th>{ts}Payment Method{/ts}</th>
-    <th>{ts}Check{/ts} #</th>
-    <th>{ts}Transaction ID{/ts}</th>
-    <th>{ts}Transaction Date{/ts}</th>
-</tr>
+  <h3>{ts}Record payments for contributions{/ts}</h3>
+  <div class="help">
+    <p>{ts}Use this form to record received payments for "pay later" online contributions, membership signups and event registrations. You can use the Transaction ID field to record account+check number, bank transfer identifier, or other unique payment identifier.{/ts}</p>
+    <p>{ts}The contribution status will be updated as appropriate.  To update contribution statuses directly, return to the search results and select "Update multiple contributions".{/ts}</p>
+  </div>
+
+  <table class="form-layout-compressed">
+    <tr class="crm-contribution-form-block-is_email_receipt">
+      <td class="label">{$form.is_email_receipt.label}</td>
+      <td class="html-adjust">{$form.is_email_receipt.html}<br />
+        <span class="description">{ts}When checked CiviCRM will send an e-mail receipt to the donor. Leave unchecked when you don't want to send an e-mail.{/ts}</span>
+      </td>
+    </tr>
+  </table>
+  <table>
+    <tr class="columnheader">
+      <th>{ts}Name{/ts}</th>
+      <th class="right">{ts}Amount{/ts}&nbsp;&nbsp;</th>
+      <th>{ts}Source{/ts}</th>
+      <th>{ts}Fee Amount{/ts}</th>
+      <th>{ts}Payment Method{/ts}</th>
+      <th>{ts}Check{/ts} #</th>
+      <th>{ts}Transaction ID{/ts}</th>
+      <th>{ts}Transaction Date{/ts}</th>
+    </tr>
 
-{foreach from=$rows item=row}
-<tr class="{cycle values="odd-row,even-row"}">
-    <td>{$row.display_name}</td>
-    <td class="right nowrap">{$row.amount|crmMoney}&nbsp;&nbsp;</td>
-    <td>{$row.source}</td>
-    {assign var="element_name" value="fee_amount_"|cat:$row.contribution_id}
-    <td>{$form.$element_name.html}</td>
-    {assign var="element_name" value="payment_instrument_id_"|cat:$row.contribution_id}
-    <td class="form-text four">{$form.$element_name.html}</td>
-    {assign var="element_name" value="check_number_"|cat:$row.contribution_id}
-    <td class="form-text four">{$form.$element_name.html|crmAddClass:four}</td>
-    {assign var="element_name" value="trxn_id_"|cat:$row.contribution_id}
-    <td>{$form.$element_name.html|crmAddClass:eight}</td>
-    {assign var="element_name" value="trxn_date_"|cat:$row.contribution_id}
-    <td>{$form.$element_name.html}</td>
-</tr>
-{/foreach}
-</table>
+    {foreach from=$rows item=row}
+    <tr class="{cycle values="odd-row,even-row"}">
+      <td>{$row.display_name}</td>
+      <td class="right nowrap">{$row.amount|crmMoney}&nbsp;&nbsp;</td>
+      <td>{$row.source}</td>
+      {assign var="element_name" value="fee_amount_"|cat:$row.contribution_id}
+      <td>{$form.$element_name.html}</td>
+      {assign var="element_name" value="payment_instrument_id_"|cat:$row.contribution_id}
+      <td class="form-text four">{$form.$element_name.html}</td>
+      {assign var="element_name" value="check_number_"|cat:$row.contribution_id}
+      <td class="form-text four">{$form.$element_name.html|crmAddClass:four}</td>
+      {assign var="element_name" value="trxn_id_"|cat:$row.contribution_id}
+      <td>{$form.$element_name.html|crmAddClass:eight}</td>
+      {assign var="element_name" value="trxn_date_"|cat:$row.contribution_id}
+      <td>{$form.$element_name.html}</td>
+    </tr>
+    {/foreach}
+  </table>
   <div class="crm-submit-buttons">{$form.buttons.html}</div>
-</fieldset>
 </div>
diff --git a/tests/phpunit/api/v3/ContributionTest.php b/tests/phpunit/api/v3/ContributionTest.php
index b5779446337865592541cd580a48ffa8b3c883dc..5de4e1caad346b98eb0fd19cfc3b93938bb25b66 100644
--- a/tests/phpunit/api/v3/ContributionTest.php
+++ b/tests/phpunit/api/v3/ContributionTest.php
@@ -2905,7 +2905,10 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->callAPISuccess('contribution', 'completetransaction', ['id' => $contribution['id'], 'trxn_date' => date('Y-m-d')]);
     $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id'], 'sequential' => 1]);
     $this->assertEquals('Completed', $contribution['values'][0]['contribution_status']);
-    $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contribution['values'][0]['receive_date'])));
+    // Make sure receive_date is original date and make sure payment date is today
+    $this->assertEquals('2012-05-11', date('Y-m-d', strtotime($contribution['values'][0]['receive_date'])));
+    $payment = $this->callAPISuccess('payment', 'get', ['contribution_id' => $contribution['id'], 'sequential' => 1]);
+    $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($payment['values'][0]['trxn_date'])));
     $mut->checkMailLog([
       'Receipt - Contribution',
       'receipt_date:::' . date('Ymd'),
@@ -3184,7 +3187,11 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->assertEquals(1, $status);
     $mut->checkMailLog([
       'amount:::500.00',
-      'receive_date:::20130201000000',
+      // The `receive_date` should remain as it was created.
+      // TODO: the latest payment transaction date (and maybe other details,
+      // such as amount and payment instrument) would be a useful token to make
+      // available.
+      'receive_date:::20120511000000',
       "receipt_date:::\n",
     ]);
     $mut->stop();
@@ -4738,4 +4745,30 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     return $result;
   }
 
+  /**
+   * Make sure that recording a payment doesn't alter the receive_date of a
+   * pending contribution.
+   */
+  public function testPaymentDontChangeReceiveDate() {
+    $params = [
+      'contact_id' => $this->_individualId,
+      'total_amount' => 100,
+      'receive_date' => '2020-02-02',
+      'contribution_status_id' => 'Pending',
+    ];
+    $contributionID = $this->contributionCreate($params);
+    $paymentParams = [
+      'contribution_id' => $contributionID,
+      'total_amount' => 100,
+      'trxn_date' => '2020-03-04',
+    ];
+    $this->callAPISuccess('payment', 'create', $paymentParams);
+
+    //check if contribution status is set to "Completed".
+    $contribution = $this->callAPISuccess('Contribution', 'getSingle', [
+      'id' => $contributionID,
+    ]);
+    $this->assertEquals('2020-02-02 00:00:00', $contribution['receive_date']);
+  }
+
 }
diff --git a/tests/phpunit/api/v3/PaymentTest.php b/tests/phpunit/api/v3/PaymentTest.php
index c01bf4b60829a788b9f8e740af85491642485d2a..19ff25b8f1a833020f6bdf19583e457fef6da60d 100644
--- a/tests/phpunit/api/v3/PaymentTest.php
+++ b/tests/phpunit/api/v3/PaymentTest.php
@@ -1124,9 +1124,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     $this->assertEquals($trxnID, $contribution['trxn_id'],
       "Contribution trxn_id should have been set to that of the payment.");
 
-    // change $trxnDate for $receiveDate if we agree that transactions should NOT
-    // update contributions.
-    $this->assertEquals($trxnDate, $contribution['receive_date'],
+    $this->assertEquals($originalReceiveDate, $contribution['receive_date'],
       "Contribution receive date was changed, but should not have been.");
 
     $this->validateAllPayments();