Problem solved.
For those trying to get this working under DPM, the trick is that you don't create the message using the login ID, transaction ID and amount, as suggested in the conversion docs, but you use that ugly 30 field string.
Here's a PHP segment that worked for me:
$key1 = '^' . $_POST[x_trans_id]
. '^' . $_POST[x_test_request]
. '^' . $_POST[x_response_code]
. '^' . $_POST[x_auth_code]
. '^' . $_POST[x_cvv2_resp_code]
. '^' . $_POST[x_cavv_response]
. '^' . $_POST[x_avs_code]
. '^' . $_POST[x_method]
. '^' . $_POST[x_account_number]
. '^' . $_POST[x_amount]
. '^' . $_POST[x_company]
. '^' . $_POST[x_first_name]
. '^' . $_POST[x_last_name]
. '^' . $_POST[x_address]
. '^' . $_POST[x_city]
. '^' . $_POST[x_state]
. '^' . $_POST[x_zip]
. '^' . $_POST[x_country]
. '^' . $_POST[x_phone]
. '^' . $_POST[x_fax]
. '^' . $_POST[x_email]
. '^' . $_POST[x_ship_to_company]
. '^' . $_POST[x_ship_to_first_name]
. '^' . $_POST[x_ship_to_last_name]
. '^' . $_POST[x_ship_to_address]
. '^' . $_POST[x_ship_to_city]
. '^' . $_POST[x_ship_to_state]
. '^' . $_POST[x_ship_to_zip]
. '^' . $_POST[x_ship_to_country]
. '^' . $_POST[x_invoice_num]
. '^;