$value) { $log .= "\n$key: $value"; $value = urlencode($value); $req .= "&$key=$value"; } // assign posted variables to local variables $item_name = isset($_POST['item_name']) ? $_POST['item_name'] : ''; $item_number = isset($_POST['item_number']) ? $_POST['item_number'] : ''; $payment_status = isset($_POST['payment_status']) ? $_POST['payment_status'] : ''; $mc_gross = isset($_POST['mc_gross']) ? $_POST['mc_gross'] : ''; $mc_currency = isset($_POST['mc_currency']) ? $_POST['mc_currency'] : ''; $txn_id = isset($_POST['txn_id']) ? $_POST['txn_id'] : ''; $receiver_email = isset($_POST['receiver_email']) ? $_POST['receiver_email'] : ''; $payer_email = isset($_POST['payer_email']) ? $_POST['payer_email'] : ''; $custom = isset($_POST['custom']) ? $_POST['custom'] : ''; $txn_type = isset($_POST['txn_type']) ? $_POST['txn_type'] : ''; $subscr_id = isset($_POST['subscr_id']) ? $_POST['subscr_id'] : ''; $needs_review = 1; $status = 'unknown'; $ch = curl_init($GLOBALS['paypal_site'] . '/cgi-bin/webscr'); if ($ch == false) { $status = 'curl_init failed'; } else { curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close')); $res = curl_exec($ch); $curl_errno = curl_errno($ch); curl_close($ch); if ($curl_errno != 0) { $status = 'curl fail: ' . $curl_errno; } else { // Split response headers and payload, a better way for strcmp $tokens = explode("\r\n\r\n", trim($res)); $res = trim(end($tokens)); $res_word = trim($tokens[count($tokens) - 1]); if ($res_word === 'VERIFIED') { $status = 'verified'; } elseif ($res_word === 'INVALID') { $status = 'invalid'; } else { $log .= "\n\nCan't figure out PayPal verify reply:\n" . $res; } } } $row = [ 'txn_id' => $txn_id, 'status' => $status, 'custom' => $custom, 'item_name' => $item_name, 'item_number' => $item_number, 'needs_review' => $needs_review, 'payment_status' => $payment_status, 'mc_gross' => $mc_gross, 'mc_currency' => $mc_currency, 'receiver_email' => $receiver_email, 'payer_email' => $payer_email, 'log' => $log, 'txn_type' => $txn_type, 'subscr_id' => $subscr_id, 'user_id' => $user_id, 'ipn_at' => time() ]; db_insert_assoc('paypal_ipn', $row); $row['id'] = $ipn_id = db_auto_id(); if($status !== 'verified') { # it's really from PayPal paypal_ipn_main_debug("status is not \"verified\" but is \"$status\""); } elseif ($txn_type !== 'subscr_payment' && $txn_type !== 'web_accept') { if ($txn_type !== 'subscr_signup' && $txn_type !== 'subscr_cancel' && $txn_type !== 'subscr_eot') { # subscr_cancel is sent when they cancel. After that: # subscr_eot is sent when their next payment would have been paypal_ipn_main_debug("txn_type is not \"subscr_payment\", \"subscr_signup\", \"subscr_cancel\", \"subscr_eot\" or \"web_accept\" but is \"$txn_type\""); } } elseif ($payment_status !== 'Completed') { # payment has completed if ($payment_status !== 'Pending') { paypal_ipn_main_debug("payment_status is not \"Completed\" or \"Pending\", but is \"$payment_status\""); } } elseif ($receiver_email !== $GLOBALS['paypal_email']) { paypal_ipn_main_debug("payment isn't to us ($GLOBALS[paypal_email]) but to \"$receiver_email\""); } elseif ($mc_currency !== 'USD') { paypal_ipn_main_debug("Currency isn't \"USD\" but is \"$mc_currency\""); } else { $custom_words = explode(' ', $custom); if (!isset($GLOBALS['payment_handlers'][$custom_words[0]])) { paypal_ipn_main_debug("\$custom's first word isn't in GLOBALS[payment_handlers]. \$custom: \"$custom\""); } else { $ret = file_run($GLOBALS['payment_handlers'][$custom_words[0]], $custom_words, $mc_gross, $row); if ($ret and is_array($ret) and isset($ret['success']) and $ret['success']) { $update = ['processed' => '1']; if (isset($ret['for_table_id']) and isset($ret['for_row_id'])) { $tid = format_int_0((string)$ret['for_table_id']); $rid = format_int_0((string)$ret['for_row_id']); if ((int)$tid > 0 and (int)$rid > 0) { $update['for_table_id'] = $tid; $update['for_row_id'] = $rid; } } db_update_assoc('paypal_ipn', $update); } else { paypal_ipn_main_debug($user, $old_date, $was_expired); } } } } function paypal_ipn_main_debug($message) { $message = this_host() . ' paypal payment failure ' . $_POST['ipn_track_id'] . "\n\n" . $message; $message .= "\n\nDump of all info received:\n"; foreach ($_POST as $key => $value) { $message .= "\t$key: $value\n"; } $template_vars = ['details' => $message]; email_with_template(null, 'backend_debug', $template_vars); } # this file is accessed directly from the paypal IPN system ini_set('display_errors', '0'); ini_set('log_errors', '1'); paypal_ipn_main();