/** * Handles the payment update (note: mijireh doesn't send an IPN in the usual sense, * instead they just redirect the user back to our website and then we need to query them * for the payment's status). Also note that the $update_info should be an array with the key * 'payment' containing the EEI_Payment to update * @param array $update_info unused. We just use the $transaction * @param EEI_Transaction $transaction * @throws EE_Error */ public function handle_payment_update($update_info, $transaction) { $payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : NULL; if ($payment && $payment instanceof EEI_Payment) { $url = 'https://secure.mijireh.com/api/1/orders/' . $payment->txn_id_chq_nmbr(); $request_args = array('headers' => array('Authorization' => 'Basic ' . base64_encode($this->_access_key . ':'), 'Accept' => 'application/json')); $response = wp_remote_get($url, $request_args); $this->log(array('get payment status request_args' => $request_args, 'response' => $response), $payment); if ($response && isset($response['body']) && ($response_body = json_decode($response['body']))) { switch ($response_body->status) { case 'paid': $payment->set_status($this->_pay_model->approved_status()); break; case 'pending': $payment->set_status($this->_pay_model->pending_status()); break; default: $payment->set_status($this->_pay_model->declined_status()); } } else { $payment->set_gateway_response(__('Response from Mijireh could not be understood.', 'event_espresso')); $payment->set_details($response); $payment->set_status($this->_pay_model->failed_status()); } return $payment; } else { throw new EE_Error(sprintf(__("Could not find Mijireh payment for transaction %s", 'event_espresso'), $transaction->ID())); } }
/** * Often used for IPNs. But applies the info in $update_info to the payment. * What is $update_info? Often the contents of $_REQUEST, but not necessarily. Whatever * the payment method passes in. * @param array $update_info like $_POST * @param EEI_Transaction $transaction * @return \EEI_Payment updated * @throws \EE_Error */ public function handle_payment_update($update_info, $transaction) { //verify there's payment data that's been sent if (empty($update_info['payment_status']) || empty($update_info['txn_id'])) { // waaaait... is this a PDT request? (see https://developer.paypal.com/docs/classic/products/payment-data-transfer/) // indicated by the "tx" argument? If so, we don't need it. We'll just use the IPN data when it comes if (isset($update_info['tx'])) { return $transaction->last_payment(); } else { return null; } } $payment = $this->_pay_model->get_payment_by_txn_id_chq_nmbr($update_info['txn_id']); if (!$payment instanceof EEI_Payment) { $payment = $transaction->last_payment(); } // ok, then validate the IPN. Even if we've already processed this payment, // let PayPal know we don't want to hear from them anymore! if (!$this->validate_ipn($update_info, $payment)) { return $payment; } //ok, well let's process this payment then! switch ($update_info['payment_status']) { case 'Completed': $status = $this->_pay_model->approved_status(); $gateway_response = __('The payment is approved.', 'event_espresso'); break; case 'Pending': $status = $this->_pay_model->pending_status(); $gateway_response = __('The payment is in progress. Another message will be sent when payment is approved.', 'event_espresso'); break; case 'Denied': $status = $this->_pay_model->declined_status(); $gateway_response = __('The payment has been declined.', 'event_espresso'); break; case 'Expired': case 'Failed': $status = $this->_pay_model->failed_status(); $gateway_response = __('The payment failed for technical reasons or expired.', 'event_espresso'); break; case 'Refunded': case 'Partially_Refunded': // even though it's a refund, we consider the payment as approved, it just has a negative value $status = $this->_pay_model->approved_status(); $gateway_response = __('The payment has been refunded. Please update registrations accordingly.', 'event_espresso'); break; case 'Voided': case 'Reversed': case 'Canceled_Reversal': default: $status = $this->_pay_model->cancelled_status(); $gateway_response = __('The payment was cancelled, reversed, or voided. Please update registrations accordingly.', 'event_espresso'); break; } //check if we've already processed this payment if ($payment instanceof EEI_Payment) { //payment exists. if this has the exact same status and amount, don't bother updating. just return if ($payment->status() == $status && $payment->amount() == $update_info['mc_gross']) { // DUPLICATED IPN! dont bother updating transaction foo!; $message_log = sprintf(__('It appears we have received a duplicate IPN from PayPal for payment %d', 'event_espresso'), $payment->ID()); } else { // new payment yippee !!! $payment->set_status($status); $payment->set_amount(floatval($update_info['mc_gross'])); $payment->set_gateway_response($gateway_response); $payment->set_details($update_info); $payment->set_txn_id_chq_nmbr($update_info['txn_id']); $message_log = sprintf(__('Updated payment either from IPN or as part of POST from PayPal', 'event_espresso')); } $this->log(array('url' => $this->_process_response_url(), 'message' => $message_log, 'payment' => $payment->model_field_array(), 'IPN_data' => $update_info), $payment); } do_action('FHEE__EEG_Paypal_Standard__handle_payment_update__payment_processed', $payment, $this); // kill request here if this is a refund if ($update_info['payment_status'] == 'Refunded' || $update_info['payment_status'] == 'Partially_Refunded') { if (apply_filters('FHEE__EEG_Paypal_Standard__handle_payment_update__kill_refund_request', true)) { status_header(200); exit; } } return $payment; }
/** * Handles the payment update (note: mijireh doesn't send an IPN in the usual sense, * instead they just redirect the user back to our website and then we need to query them * for the payment's status). Also note that the $update_info should be an array with the key * 'payment' containing the EEI_Payment to update * * @param array $update_info unused. We just use the $transaction * @param EEI_Transaction $transaction * @return \EEI_Payment|null */ public function handle_payment_update($update_info, $transaction) { $payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : NULL; if (!$payment instanceof EEI_Payment) { throw new EE_Error(sprintf(__("Could not find Mijireh payment for transaction %s", 'event_espresso'), $transaction->ID())); } $request_args = array('headers' => array('Authorization' => 'Basic ' . base64_encode($this->_access_key . ':'), 'Accept' => 'application/json')); $response = wp_remote_get($this->_mijireh_api_orders_url . '/' . $payment->txn_id_chq_nmbr(), $request_args); $this->log(array('get payment status request_args' => $request_args, 'response' => $response), $payment); // validate response $response_body = isset($response['body']) ? json_decode($response['body']) : ''; if ($response && $response_body) { switch ($response_body->status) { case 'paid': $payment->set_status($this->_pay_model->approved_status()); break; case 'pending': $payment->set_status($this->_pay_model->pending_status()); break; default: $payment->set_status($this->_pay_model->declined_status()); } } else { $payment->set_gateway_response(__('Response from Mijireh could not be understood.', 'event_espresso')); $payment->set_details($response); $payment->set_status($this->_pay_model->failed_status()); } // the following is ONLY for testing the Mijireh IPN and should NEVER be uncommented for real usage // $payment->set_status( $this->_pay_model->pending_status() ); return $payment; }