/** * @param $url * @param $data * @param int $ttl * @param string $caCertPath * @return array */ public static function requestPost($url, $data, $ttl = 30, $caCertPath = '') { set_time_limit(60); $output = array(); $curlSession = curl_init(); curl_setopt($curlSession, CURLOPT_URL, $url); curl_setopt($curlSession, CURLOPT_HEADER, 0); curl_setopt($curlSession, CURLOPT_POST, 1); curl_setopt($curlSession, CURLOPT_POSTFIELDS, SagepayUtil::arrayToQueryString($data, '&', true)); curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curlSession, CURLOPT_TIMEOUT, $ttl); curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 2); if (!empty($caCertPath)) { curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($curlSession, CURLOPT_CAINFO, $caCertPath); } else { curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, 0); } $rawresponse = curl_exec($curlSession); if (curl_getinfo($curlSession, CURLINFO_HTTP_CODE) !== 200) { $output['Status'] = "FAIL"; $output['StatusDetails'] = "Server Response: " . curl_getinfo($curlSession, CURLINFO_HTTP_CODE); $output['Response'] = $rawresponse; return $output; } if (curl_error($curlSession)) { $output['Status'] = "FAIL"; $output['StatusDetail'] = curl_error($curlSession); $output['Response'] = $rawresponse; return $output; } curl_close($curlSession); $response = SagepayUtil::queryStringToArray($rawresponse, "\r\n"); return array_merge($output, $response); }
/** * Redirect to location * * @param string $controller * @param string $action * @param array $query */ protected function redirect($controller, $action = 'index', $query = array()) { $queryStr = ''; // Check if query is not empty if (count($query) > 0) { $queryStr = '?' . SagepayUtil::arrayToQueryString($query, '&', true); } if ($controller == 'index') { $args = array(''); } else { $args = array($controller, $action); } header('Location: ' . url($args) . $queryStr); exit; }
/** * Action authorise the transaction */ public function actionAuthorise() { $errorMessage = ''; // Check if form was submitted if (filter_input(INPUT_POST, 'origVtx')) { $payment = new ModelPayment(); $paymentTxOrig = $payment->getByVendorTxCode(filter_input(INPUT_POST, 'origVtx')); $data = array('VPSProtocol' => $this->sagepayConfig->getProtocolVersion(), 'TxType' => SAGEPAY_TXN_AUTHORISE, 'Vendor' => $this->sagepayConfig->getVendorName(), 'VendorTxCode' => filter_input(INPUT_POST, 'VendorTxCode'), 'Amount' => filter_input(INPUT_POST, 'Amount'), 'Description' => filter_input(INPUT_POST, 'Description'), 'RelatedVPSTxID' => $paymentTxOrig['vpsTxId'], 'RelatedVendorTxCode' => filter_input(INPUT_POST, 'origVtx'), 'RelatedSecurityKey' => $paymentTxOrig['securityKey'], 'ApplyAVSCV2' => filter_input(INPUT_POST, 'ApplyAvsCv2')); $errorMessage = $this->validateAuthoriseAction($paymentTxOrig, $data); // Check if authorise was failed if (!$errorMessage) { $response = SagepayCommon::requestPost($this->sagepayConfig->getSharedUrl('authorise'), $data); if ($response['Status'] == SAGEPAY_REMOTE_STATUS_OK) { $paymentTxOrig['CapturedAmount'] = $paymentTxOrig['capturedAmount'] + filter_input(INPUT_POST, 'Amount'); $paymentTxOrig['Status'] = SAGEPAY_REMOTE_STATUS_AUTHENTICATED; $payment->update(filter_input(INPUT_POST, 'origVtx'), $paymentTxOrig); $paymentTxOrig = $this->ucFirstFields($paymentTxOrig); $paymentTx = array_merge($paymentTxOrig, $data, $response); $paymentTx['StatusDetail'] = SAGEPAY_TXN_AUTHORISE . ' transaction taken through Order Admin area.'; $paymentTx['CapturedAmount'] = filter_input(INPUT_POST, 'Amount'); $payment->insert($paymentTx); } $query = array('requestBody' => SagepayUtil::arrayToQueryString($data), 'resultBody' => SagepayUtil::arrayToQueryString($response), 'status' => $response['Status'], 'command' => SAGEPAY_TXN_AUTHORISE); $this->redirect($this->integrationType, 'admin_result', $query); } } else { if (filter_input(INPUT_GET, 'origVtx')) { $payment = new ModelPayment(); $paymentTxOrig = $payment->getByVendorTxCode(filter_input(INPUT_GET, 'origVtx')); } else { $this->redirect($this->integrationType, 'admin'); } } $view = new HelperView('admin/authorise'); $view->setData(array('env' => $this->sagepayConfig->getEnv(), 'vendorName' => $this->sagepayConfig->getVendorName(), 'integrationType' => $this->integrationType, 'result' => $paymentTxOrig, 'val' => array('ok' => true), 'newVtx' => SagepayCommon::vendorTxCode(time(), SAGEPAY_TXN_AUTHORISE, $this->sagepayConfig->getVendorName()), 'actionUrl' => url(array($this->integrationType, 'authorise')) . '?origVtx=' . filter_input(INPUT_GET, 'origVtx'), 'error' => $errorMessage ? true : false, 'message' => $errorMessage)); $view->render(); }
function eme_sagepay_form($event, $payment, $price, $lang, $multi_booking = 0) { global $post; $charge = eme_payment_provider_extra_charge($price, 'fdgg'); $price += $charge; $events_page_link = eme_get_events_page(true, false); $payment_id = $payment['id']; if ($multi_booking) { $success_link = get_permalink($post->ID); $fail_link = $success_link; $name = __("Multiple booking request", "eme"); } else { $success_link = eme_payment_return_url($event, $payment, 1); $fail_link = eme_payment_return_url($event, $payment, 2); $name = eme_sanitize_html(sprintf(__("Booking for '%s'", "eme"), $event['event_name'])); } // sagepay doesn't use a notification url, but sends the status along as part of the return url // so we add the notification info to it too, so we can process payed info as usual $success_link = add_query_arg(array('eme_eventAction' => 'sagepay_notification'), $success_link); $fail_link = add_query_arg(array('eme_eventAction' => 'sagepay_notification'), $fail_link); $vendor_name = get_option('eme_sagepay_vendor_name'); // the live or sandbox url $sagepay_demo = get_option('eme_sagepay_demo'); if ($sagepay_demo == 1) { $sagepay_pwd = get_option('eme_sagepay_test_pwd'); $url = SAGEPAY_SANDBOX_URL; } else { $sagepay_pwd = get_option('eme_sagepay_live_pwd'); $url = SAGEPAY_LIVE_URL; } $cur = $event['currency']; $button_above = eme_replace_payment_provider_placeholders(get_option('eme_sagepay_button_above'), $charge, $event['currency'], $lang); $button_label = eme_replace_payment_provider_placeholders(get_option('eme_sagepay_button_label'), $charge, $event['currency'], $lang); $button_below = eme_replace_payment_provider_placeholders(get_option('eme_sagepay_button_below'), $charge, $event['currency'], $lang); $button_img_url = get_option('eme_sagepay_button_img_url'); $query = array('VendorTxCode' => $payment_id, 'Amount' => number_format($price, 2, '.', ''), 'Currency' => $cur, 'Description' => $name, 'SuccessURL' => $success_link, 'FailureURL' => $fail_link); require_once 'payment_gateways/sagepay/eme-sagepay-util.php'; $crypt = SagepayUtil::encryptAes(SagepayUtil::arrayToQueryString($query), $sagepay_pwd); $form_html = $button_above; $form_html .= "<form action='{$url}' method='post'>"; $form_html .= "<input type='hidden' name='VPSProtocol' value='3.00' />"; $form_html .= "<input type='hidden' name='TxType' value='PAYMENT' />"; $form_html .= "<input type='hidden' name='Vendor' value='{$vendor_name}' />"; $form_html .= "<input type='hidden' name='Crypt' value='{$crypt}' />"; $button_label = htmlentities($button_label); if (!empty($button_img_url)) { $form_html .= "<input type='image' src='{$button_img_url}' alt='{$button_label}' title='{$button_label}' />"; } else { $form_html .= "<input type='submit' value='{$button_label}' />"; } $form_html .= "</form>"; $form_html .= $button_below; return $form_html; }
/** * Return urlencoded string based on data * * @uses SagepayUtil::arrayToQueryString * @return string */ public function getQueryData() { // Replace after implemeting right View content return SagepayUtil::arrayToQueryString($this->data); }
/** * Action register page for direct payment */ public function actionRegister() { $api = $this->buildApi(); $card = HelperCommon::getStore('card'); $siteFqdn = $this->sagepayConfig->getSiteFqdn(); // Check cardType if ($card['cardType'] == 'PAYPAL') { $api->setIntegrationMethod(SAGEPAY_PAYPAL); $this->sagepayConfig->setPaypalCallbackUrl(url('direct/paypal-response', $siteFqdn)); } $account = HelperCommon::getStore('account'); $api->setPaneValues($card + $account); $api->setVpsDirectUrl($this->purchaseUrl); $response = $api->createRequest(); $data = $api->getData(); $data += $response; // Insert in database $payment = new ModelPayment(); $payment->insert($data); // Redirect $vtxQuery = array('vtx' => $data['VendorTxCode']); if ($response['Status'] == SAGEPAY_REMOTE_STATUS_PAYPAL_REDIRECT) { header('Location: ' . $response['PayPalRedirectURL']); exit; } else { if ($response['Status'] == "3DAUTH") { $threeDSecure = array('MD' => $response['MD'], 'ACSURL' => $response['ACSURL'], 'PaReq' => $response['PAReq'], 'TermUrl' => url(array('direct', 'three-d-secure-result'), $siteFqdn) . '?' . SagepayUtil::arrayToQueryString($vtxQuery)); HelperCommon::setStore('3DAUTH', $threeDSecure); $this->redirect('direct', 'three-d-secure', $vtxQuery); } else { if (in_array($response['Status'], array(SAGEPAY_REMOTE_STATUS_OK, SAGEPAY_REMOTE_STATUS_REGISTERED))) { if ($data['TxType'] == SAGEPAY_REMOTE_STATUS_PAYMENT) { $surcharge = isset($response['Surcharge']) ? floatval($response['Surcharge']) : 0.0; $paymentTx = array('CapturedAmount' => floatval($data['Amount']) + $surcharge, 'Amount' => floatval($data['Amount']) + $surcharge); $payment->update($data['VendorTxCode'], $paymentTx); } $this->redirect('direct', 'success', $vtxQuery); } } } $this->redirect('direct', 'failure', $vtxQuery); }
/** * Encrypt the order details ready to send to SagePay Server. * * @param SagepayAbstractApi $request The request instance. * @throws SagepayApiException * * @return array|string Returns a String for Form integration method or an array for Server / Direct. */ public static function encryptedOrder(SagepayAbstractApi $request) { $settings = $request->getConfig(); $basket = $request->getBasket(); $address = $request->getAddressList(); $integrationMethod = $request->getIntegrationMethod(); $paneValues = $request->getPaneValues(); // Determine the transaction type based on the payment gateway settings. $txType = $settings->getTxType(); $billingAddress = $address[0]; $deliveryAddress = isset($address[1]) ? $address[1] : null; $query = array('VPSProtocol' => $settings->getProtocolVersion(), 'Vendor' => $settings->getVendorName(), 'VendorTxCode' => self::vendorTxCode($basket->getId(), $txType, $settings->getVendorName()), 'Amount' => number_format($basket->getAmount(), 2, '.', ''), 'Currency' => $settings->getCurrency(), 'Description' => $basket->getDescription(), 'CustomerName' => $billingAddress->firstname . ' ' . $billingAddress->lastname, 'CustomerEMail' => $billingAddress->email, 'VendorEMail' => $settings->getVendorEmail(), 'SendEMail' => $settings->getSendEmail(), 'eMailMessage' => $settings->getEmailMessage(), 'BillingSurname' => $billingAddress->lastname, 'BillingFirstnames' => $billingAddress->firstname, 'BillingAddress1' => $billingAddress->address1, 'BillingAddress2' => $billingAddress->address2, 'BillingCity' => $billingAddress->city, 'BillingPostCode' => $billingAddress->getPostCode(), 'BillingCountry' => $billingAddress->country, 'BillingPhone' => $billingAddress->phone, 'ApplyAVSCV2' => $settings->getApplyAvsCv2(), 'Apply3DSecure' => $settings->getApply3dSecure(), 'AllowGiftAid' => $settings->getAllowGiftAid(), 'BillingAgreement' => $settings->getBillingAgreement()); $query += $request->getData(); $customer = $request->getCustomer(); if ($customer instanceof SagepayCustomer) { $query += self::_setAuxValue($query, 'CustomerXML', $customer->export()); } $query += self::_setAuxValue($query, 'VendorData', $settings->getVendorData()); $query += self::_setAuxValue($query, 'ReferrerID', $settings->getPartnerId()); $query += self::_setAuxValue($query, 'Language', $settings->getLanguage()); // Add check for state for US addresses only. if ($billingAddress->country == 'US') { $query['BillingState'] = $billingAddress->state; } //Override with supplied delivery address if we have one . $query += self::_populateDeliveryDetails($billingAddress, $deliveryAddress); if (isset($paneValues['cardType']) && empty($paneValues['cardType'])) { $integrationMethod = SAGEPAY_TOKEN; } // Check if we need to encode cart. if (!$settings->basketAsXmlDisabled()) { $query['BasketXML'] = $basket->exportAsXml(); } else { $query['Basket'] = $basket->exportAsXml(false); } if (count($settings->getSurcharges()) > 0) { $surcharges = new SagepaySurcharge(); $surcharges->setSurcharges($settings->getSurcharges()); $query['SurchargeXML'] = $surcharges->export(); } switch ($integrationMethod) { case SAGEPAY_FORM: // Unset unused values unset($query['VPSProtocol']); unset($query['Vendor']); unset($query['TxType']); $env = $settings->getEnv(); $query['SuccessURL'] = $settings->getFullFormSuccessUrl(); $query['FailureURL'] = $settings->getFullFormFailureUrl(); $request->setData($query); $queryStr = SagepayUtil::arrayToQueryString($query); $formValues = array(); $formValues['Vendor'] = $settings->getVendorName(); $formValues['VPSProtocol'] = $settings->getProtocolVersion(); $formValues['TxType'] = $txType; $formValues['Crypt'] = SagepayUtil::encryptAes($queryStr, $settings->getFormEncryptionPassword($env)); // Encrypt order details using base64 and the secret key from the settings. return $formValues; case SAGEPAY_SERVER: $query['NotificationURL'] = $settings->getFullServerNotificationUrl(); $query['TxType'] = $txType; $query['Profile'] = $settings->getServerProfile(); $query['StoreToken'] = 1; $query += self::_setAuxValue($query, 'AccountType', $settings->getAccountType()); return $query; case SAGEPAY_DIRECT: $query = array_merge($query, self::_getCardDetails($paneValues)); $query['TxType'] = $txType; $query['CardHolder'] = $billingAddress->firstname . ' ' . $billingAddress->lastname; // Add 3D Secure flag only if the 3d Secure module is enabled for DIRECT. $query['Apply3DSecure'] = $settings->getApply3dSecure(); $query += self::_setAuxValue($query, 'AccountType', $settings->getAccountType()); return $query; case SAGEPAY_PAYPAL: $query['TxType'] = $txType; $query['CardType'] = 'PAYPAL'; $query['PayPalCallbackURL'] = $settings->getPaypalCallbackUrl() . '?vtx=' . $query['VendorTxCode']; return $query; case SAGEPAY_TOKEN: $query['TxType'] = $txType; $query['Token'] = $paneValues['token']; $query['CV2'] = $paneValues['cv2']; $query['AllowGiftAid'] = $paneValues['giftAid'] ? 1 : 0; $query += self::_setAuxValue($query, 'AccountType', $settings->getAccountType()); $query['StoreToken'] = 1; $query['ApplyAVSCV2'] = 2; return $query; default: throw new SagepayApiException('Invalid integration type'); } }
/** * Notify page, used for server ONLY */ public function actionNotify() { $payment = new ModelPayment(); $result = $payment->getByVendorTxCode(filter_input(INPUT_POST, 'VendorTxCode')); $siteFqdn = $this->sagepayConfig->getSiteFqdn(); SagepayUtil::log('NOTIFY:' . PHP_EOL . json_encode(filter_input_array(INPUT_POST))); $vtxData = filter_input_array(INPUT_POST); if (in_array(filter_input(INPUT_POST, 'Status'), array(SAGEPAY_REMOTE_STATUS_OK, SAGEPAY_REMOTE_STATUS_AUTHENTICATED, SAGEPAY_REMOTE_STATUS_REGISTERED))) { $surcharge = floatval(filter_input(INPUT_POST, 'Surcharge', FILTER_VALIDATE_FLOAT)); $vtxData['Amount'] = $result['amount'] + $surcharge; if (filter_input(INPUT_POST, 'TxType') == SAGEPAY_REMOTE_STATUS_PAYMENT) { $vtxData['CapturedAmount'] = $vtxData['Amount']; } $data = array("Status" => SAGEPAY_REMOTE_STATUS_OK, "RedirectURL" => $siteFqdn . 'server/success?vtx=' . filter_input(INPUT_POST, 'VendorTxCode'), "StatusDetail" => 'The transaction was successfully processed.'); } else { $data = array("Status" => SAGEPAY_REMOTE_STATUS_OK, "RedirectURL" => $siteFqdn . 'server/failure?vtx=' . filter_input(INPUT_POST, 'VendorTxCode'), "StatusDetail" => filter_input(INPUT_POST, 'StatusDetail')); } $vtxData['AllowGiftAid'] = filter_input(INPUT_POST, 'GiftAid'); $payment->update(filter_input(INPUT_POST, 'VendorTxCode'), $vtxData); echo SagepayUtil::arrayToQueryString($data, "\n"); }