From 4ada51dd7ac06a3f4c0f5ac9e0353cff4c274824 Mon Sep 17 00:00:00 2001 From: Steve Sutton Date: Fri, 5 Apr 2019 07:46:28 -0400 Subject: [PATCH] Updating square payment gateway class Creating square payment Proccessing class. --- .../Square/paymentGateway.php | 651 ++++++------------ 1 file changed, 205 insertions(+), 446 deletions(-) diff --git a/lib/paymentProcessors/Square/paymentGateway.php b/lib/paymentProcessors/Square/paymentGateway.php index 27effbe0..fad1a53c 100755 --- a/lib/paymentProcessors/Square/paymentGateway.php +++ b/lib/paymentProcessors/Square/paymentGateway.php @@ -1,6 +1,6 @@ account = $account; - // Set Authorize.net environment - $this->account['environment'] = 'SANDBOX'; - if ($this->account['test'] == 0) { - $this->account['environment'] = 'PRODUCTION'; - } - // Common setup for API credentials - $this->merchantAuthentication = new AnetAPI\MerchantAuthenticationType(); - $this->merchantAuthentication->setName($account['login']); - $this->merchantAuthentication->setTransactionKey($account['key']); + $this->merchantAuthentication = array( + 'prod_app_id' => $account['prod_app_id'], + 'prod_access_token' => $account['prod_access_token'], + 'prod_location_id' => $account['prod_location_id'], + 'sandbox_app_id' => $account['sandbox_app_id'], + 'sandbox_access_token' => $account['sandbox_access_token'], + 'sandbox_location_id' => $account['sandbox_location_id'], + 'use_prod' => $account['use_prod'], + ); } @@ -157,7 +142,7 @@ class PaymentGateway * 7 Card declined * statusText Short name of status * authCode Authorization code - blank if card not accepted - * transId Authorize.Net Transaction ID for reference to this transaction + * transId Square Transaction ID for reference to this transaction * refId Our reference ID for this request - this is also sent to Authorize.net for them to store with the transaction * description Text description of result * customerProfileId Customer Profile ID - Required to use stored payment profile for future charges @@ -165,16 +150,24 @@ class PaymentGateway * profileStatus Status of stored profile request - True if stored profile information is returned * profileStatusText Text descibing status of request to store payment profile * - * Authorize.net test card numbers - * American Express 370000000000002 - * Discover 6011000000000012 - * Visa 4007000000027 - * 4012888818888 - * JCB 3088000000000017 - * Diners Club 38000000000006 - * Carte Blanche 38000000000006 + * Square Sandbox Test Card + * Brand Number CVV + * Visa 4111 1111 1111 1111 111 + * MasterCard 5105 1051 0510 5100 111 + * Discover 6011 0000 0000 0004 111 + * Diners Club 3000 0000 0000 04 111 + * JCB 3569 9900 1009 5841 111 + * American Express 3400 000000 000009 1111 + * China Union Pay 6222 9888 1234 0000 123 + * + * Square Error states + * Desired error state Test values + * Card CVV incorrect Use 911 as the CVV + * Card postal code incorrect Use 99999 as the postal code + * Card expiration date incorrect Use 01/40 as the expiration date + * */ - public function processPayment($payment = false, $customer = false) + public function processPayment( $payment = false, $customer = false ) { $errorMsg = array(); @@ -183,261 +176,160 @@ class PaymentGateway $refId = 'ref' . time(); // Check for required data ***** NEED TO ADD TO THIS TO TEST ALL NEEDED FIELDS ***** - if (!is_array($payment) || !is_array($payment)) { + if ( !is_array( $payment ) || !is_array( $payment ) ) { $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 2, - 'statusText' => 'Bad Data Supplied', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => 'The required payment and contact information was not supplied.' + 'gateway' => 'Square', + 'status' => 2, + 'statusText' => 'Bad Data Supplied', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => 'The required payment and contact information was not supplied.' ); return $resp; } - // Check for specified test mode - switch ($this->account['test']) { - - // Production Mode - case 0: - break; + # The access token to use in all Connect API requests. Use your *sandbox* access + # token if you're just testing things out. + $accessToken = ( $this->account['use_prod'] ) + ? $this->merchantAuthentication['prod_access_token'] + : $this->merchantAuthentication['sandbox_access_token']; + $locationId = ( $this->account['use_prod'] ) + ? $this->merchantAuthentication['prod_location_id'] + : $this->merchantAuthentication['sandbox_location_id']; - // Local Test - case 1: - // Always return a card approval - $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 1, - 'statusText' => 'Card Approved', - 'authCode' => '12345678', - 'transId' => '0', - 'refId' => $refId, - 'description' => '(TESTMODE) Local Test - Card Approved' - ); - return $resp; - break; + // Initialize the authorization for Square + \SquareConnect\Configuration::getDefaultConfiguration()->setAccessToken( $accessToken ); - // Fail Test - case 2: - $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 7, - 'statusText' => 'Card Declined', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => '(TESTMODE) Local Test - Card Declined' - ); - return $resp; - break; + # Helps ensure this code has been reached via form submission + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + $resp = array( + 'gateway' => 'Square', + 'status' => 2, + 'statusText' => 'Bad Data Supplied', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => 'Request not allowed' + ); + return $resp; + } - // Online Test - case 3: - // Force Use of Authorize.net SANDBOX - $this->account['environment'] = 'SANDBOX'; - break; + # Fail if the card form didn't send a value for `nonce` to the server + $nonce = $_POST['nonce']; + if (is_null($nonce)) { + $resp = array( + 'gateway' => 'Square', + 'status' => 2, + 'statusText' => 'Bad Data Supplied', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => 'Invalid card data' + ); + return $resp; + } - // Invalid test setting - default: - $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 2, - 'statusText' => 'Bad data supplied', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => 'Invalid test mode supplied - No transaction attempted' - ); - return $resp; - break; + $transactionApi = new \SquareConnect\Api\TransactionsApi(); + if ( !isset( $customer['addr1'] ) || trim( $customer['addr1'] ) == '' ) { + $errorMsg[] = 'Required Customer Address Line 1 not provided'; } - - // Test for certain required data or data content issues - if (isset($customer['id']) && trim($customer['id']) != '') { - if (strlen($customer['id']) > 20 ) { - $errorMsg[] = 'Customer ID is too long - maximum 20 characters'; - } + if ( !isset( $customer['city'] ) || trim( $customer['city'] ) == '' ) { + $errorMsg[] = 'Required Customer City not provided'; } - if (!isset($payment['name']) || trim($payment['name']) == '') { - $errorMsg[] = 'Required Vendor Name not provided'; + if ( !isset( $customer['state'] ) || trim( $customer['state'] ) == '' ) { + $errorMsg[] = 'Required Customer State not provided'; + } + if ( !isset( $customer['zip'] ) || trim( $customer['zip'] ) == '' ) { + $errorMsg[] = 'Required Customer ZIP/Postal Code not provided'; } - if (!isset($payment['transOpt']) || !in_array($payment['transOpt'], array(0,1,2))) { - $errorMsg[] = 'Invalid transaction option specified'; - } else { - - switch ($payment['transOpt']) { - - case 0: // Charge Card Only - case 1: // Charge Card and save as profile - - if (!isset($customer['fname']) || trim($customer['fname']) == '') { - $errorMsg[] = 'Required Customer First Name not provided'; - } - if (!isset($customer['lname']) || trim($customer['lname']) == '') { - $errorMsg[] = 'Required Customer Last Name not provided'; - } - if (!isset($customer['addr1']) || trim($customer['addr1']) == '') { - $errorMsg[] = 'Required Customer Address Line 1 not provided'; - } - if (!isset($customer['city']) || trim($customer['city']) == '') { - $errorMsg[] = 'Required Customer City not provided'; - } - if (!isset($customer['state']) || trim($customer['state']) == '') { - $errorMsg[] = 'Required Customer State not provided'; - } - if (!isset($customer['zip']) || trim($customer['zip']) == '') { - $errorMsg[] = 'Required Customer ZIP/Postal Code not provided'; - } -// Not requiring country at this time. - See https://developer.authorize.net/api/reference/ and search for "Country" -// if (!isset($customer['country']) || trim($customer['country']) == '') { -// $errorMsg[] = 'Required Customer Country not provided'; -// } - if (!isset($payment['charge']) || (trim($payment['charge'])-0) <= 0) { - $errorMsg[] = 'Required Charge Amount not provided'; - } - if (!isset($payment['ccnumb']) || trim($payment['ccnumb']) == '') { - $errorMsg[] = 'Required Credit Card Number not provided'; - } - if (!isset($payment['ccexp']) || trim($payment['ccexp']) == '') { - $errorMsg[] = 'Required Credit Card Expiration not provided'; - } - if (!isset($payment['cccode']) || trim($payment['cccode']) == '') { - $errorMsg[] = 'Required Credit Card Security Code not provided'; - } - - break; - - case 2: // Charge using profile - if (!isset($payment['customerProfileId']) || trim($payment['customerProfileId']) == '') { - $errorMsg[] = 'Required Customer Profile ID for charging a stored profile not provided'; - } - if (!isset($payment['paymentProfileId']) || trim($payment['paymentProfileId']) == '') { - $errorMsg[] = 'Required Payment Profile ID for charging a stored profile not provided'; - } + $buyerInfo = array( + 'buyer_email_address' => $customer['email'], + 'billing_address' => array( + 'address_line_1' => $customer['addr1'], + 'locality' => $customer['city'], + 'administrative_district_level_1' => $customer['state'], + 'postal_code' => $customer['zip'], + ), + ); - break; + $paymentInfo = array( + 'card_nonce' => $nonce, + 'idempotency_key' => uniqid(), + 'amount_money' => array( + 'amount' => $payment['charge'] * 100, + 'currency' => 'USD', + ), + ); - } + $referenceInfo = array( + 'reference_id' => '', + 'note' => '', + ); - } + $txRequest = array_merge( + $buyerInfo, + $paymentInfo, + $referenceInfo + ); - // If there's a problem with submitted information - if (count($errorMsg) > 0) { + # The SDK throws an exception if a Connect endpoint responds with anything besides + # a 200-level HTTP code. This block catches any exceptions that occur from the request. + try { + $result = $transactionApi->charge( $locationId, $txRequest ); + echo "
";
+            print_r( $result );
+            echo "
"; $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 2, - 'statusText' => 'Bad data supplied', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => implode(', ', $errorMsg) + 'gateway' => 'Square', + 'status' => 1, + 'statusText' => 'Card Approved', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => '
200 response: ' . print_r( $result, true) . '
', + ); + return $resp; + } catch ( \SquareConnect\ApiException $e ) { + $resp = array( + 'gateway' => 'Square', + 'status' => 7, + 'statusText' => 'Card Declined', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => '
Bad response: ' . print_r( $e->getResponseBody(), true) . '
' + .'
$txRequest: ' . print_r( $txRequest, true ) . '
', ); return $resp; } - // Create order information - $order = new AnetAPI\OrderType(); - if (isset($payment['invoice']) && trim($payment['invoice']) != '') { - $order->setInvoiceNumber(substr($payment['invoice'], -20)); - } - $order->setDescription($payment['name']); - - // Set the customer's identifying information - $customerIdent = new AnetAPI\CustomerDataType(); - if (isset($customer['email']) && trim($customer['email']) != '') { - $customerIdent->setEmail($customer['email']); - } - // $customerIdentData->setType("individual"); // "individual" or "business" - Not required - if (isset($customer['id']) && trim($customer['id']) != '') { - $customerIdent->setId($customer['id']); + // Test for certain required data or data content issues + if ( isset( $customer['id'] ) && trim( $customer['id'] ) != '' ) { + if (strlen($customer['id']) > 20 ) { + $errorMsg[] = 'Customer ID is too long - maximum 20 characters'; + } } - - // Create a transaction type - $transactionRequestType = new AnetAPI\TransactionRequestType(); - $transactionRequestType->setTransactionType("authCaptureTransaction"); - $transactionRequestType->setAmount($payment['charge']); - $transactionRequestType->setOrder($order); - $transactionRequestType->setCustomer($customerIdent); - - // If charge using a stored profile - if (isset($payment['transOpt']) && $payment['transOpt'] == 2) { - - // Setup payment profile - $paymentProfile = new AnetAPI\PaymentProfileType(); - $paymentProfile->setPaymentProfileId($payment['paymentProfileId']); - - // Specify profile to charge - $profileToCharge = new AnetAPI\CustomerProfilePaymentType(); - $profileToCharge->setCustomerProfileId($payment['customerProfileId']); - $profileToCharge->setPaymentProfile($paymentProfile); - - // Set transaction request type to charge profile - $transactionRequestType->setProfile($profileToCharge); - - - // Else, charge using new card data - } else { - - // Set the customer's Bill To address - $customerAddress = new AnetAPI\CustomerAddressType(); - $customerAddress->setFirstName($customer['fname']); - $customerAddress->setLastName($customer['lname']); - $customerAddress->setAddress($customer['addr1'].($customer['addr2']!=''?', '.$customer['addr2']:'')); - $customerAddress->setCity($customer['city']); - $customerAddress->setState($customer['state']); - $customerAddress->setZip($customer['zip']); - $customerAddress->setCountry($customer['country']); - // $customerAddress->setCompany(''); - - // Create the payment data for a credit card - $creditCard = new AnetAPI\CreditCardType(); - $creditCard->setCardNumber($payment['ccnumb']); - $creditCard->setExpirationDate($payment['ccexp']); - $creditCard->setCardCode($payment['cccode']); - - // Create Payment Type - $paymentType = new AnetAPI\PaymentType(); - $paymentType->setCreditCard($creditCard); - - // Set transaction request type to charge card payment type - $transactionRequestType->setBillTo($customerAddress); - $transactionRequestType->setPayment($paymentType); - + if ( !isset( $payment['name'] ) || trim( $payment['name'] ) == '' ) { + $errorMsg[] = 'Required Vendor Name not provided'; } - // Payment reference ID (up to 20 characters) for this request - Possibly supplied - $request = new AnetAPI\CreateTransactionRequest(); - $request->setMerchantAuthentication($this->merchantAuthentication); - $request->setRefId($refId); - $request->setTransactionRequest($transactionRequestType); - - // echo "TRANSACTION REQUEST
".print_r($request,1)."
"; - - // Send request to Authorize.net - ANetEvironment = CUSTOM, SANDBOX, PRODUCTION - $controller = new AnetController\CreateTransactionController($request); - - // Select processing environment - switch ($this->account['environment']) { - - case 'SANDBOX': - $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX); - break; - - case 'PRODUCTION': - $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::PRODUCTION); - break; - - default: - die('Authorise.Net Payment Gateway: Serious error - processing environment not specified in calling code!'); - break; - + // If there's a problem with submitted information + if ( count( $errorMsg ) > 0 ) { + $resp = array( + 'gateway' => 'Square', + 'status' => 2, + 'statusText' => 'Bad data supplied', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => implode(', ', $errorMsg) + ); + return $resp; } - // echo "TRANSACTION RESPONSE
".print_r($response,1)."
"; - // Assume the worst $respCode = 0; $respDescr = 'Unable to communicate with credit card processor.'; @@ -490,7 +382,7 @@ class PaymentGateway } /* - * Possible returned Authorize.net status codes + * Possible returned Square status codes * 1 = approved * 2 = declined * 3 = error @@ -498,71 +390,70 @@ class PaymentGateway */ // Determine response method - switch ($respCode) { + switch ( $respCode ) { // Approved case 1: $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 1, - 'statusText' => 'Card Approved', - 'authCode' => $transResponse->getAuthCode(), - 'transId' => $transResponse->getTransId(), - 'refId' => $refId, - 'description' => $respDescr + 'gateway' => 'Square', + 'status' => 1, + 'statusText' => 'Card Approved', + 'authCode' => $transResponse->getAuthCode(), + 'transId' => $transResponse->getTransId(), + 'refId' => $refId, + 'description' => $respDescr ); break; // Declined - case 2: $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 7, - 'statusText' => 'Card Declined', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => $respDescr + 'gateway' => 'Square', + 'status' => 7, + 'statusText' => 'Card Declined', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => $respDescr ); break; // Error case 3: $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 3, - 'statusText' => 'Transaction Error', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => $respDescr + 'gateway' => 'Square', + 'status' => 3, + 'statusText' => 'Transaction Error', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => $respDescr ); break; // Held for Review case 4: $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 7, - 'statusText' => 'Held for review', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => $response->response_reason_text + 'gateway' => 'Square', + 'status' => 7, + 'statusText' => 'Held for review', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => $response->response_reason_text ); break; // Any other response code default: $resp = array( - 'gateway' => 'Authorize.Net', - 'status' => 4, - 'statusText' => 'Bad Response', - 'authCode' => '', - 'transId' => '', - 'refId' => $refId, - 'description' => $respDescr + 'gateway' => 'Square', + 'status' => 4, + 'statusText' => 'Bad Response', + 'authCode' => '', + 'transId' => '', + 'refId' => $refId, + 'description' => $respDescr ); break; @@ -575,163 +466,31 @@ class PaymentGateway // If the transaction was not successful - if ($resp['status'] != 1) { - $resp['profileId'] = false; - $resp['profileStatus'] = false; + if ( $resp['status'] != 1 ) { + $resp['profileId'] = false; + $resp['profileStatus'] = false; $resp['profileStatusText'] = 'No profile, transaction had failed'; // Otherwise, if there's no TRansaction ID - } elseif (trim($resp['transId']) == '') { - $resp['profileId'] = false; - $resp['profileStatus'] = false; - $resp['profileStatusText'] = 'No profile, no transaction id available'; + } elseif ( trim( $resp['transId'] ) == '' ) { + $resp['profileId'] = false; + $resp['profileStatus'] = false; + $resp['profileStatusText'] = 'No profile, no transaction id available'; // Otherwise, try to create a customer profile } else { - $profileResponse = $this->createProfileFromTrans($resp['transId'], $customer); + // $profileResponse = $this->createProfileFromTrans($resp['transId'], $customer); // Add profile request result to transaction result - $resp = array_merge($resp, $profileResponse); - - } - - } - - return $resp; - - } - - /** - * Create Customer Profile (saved card info) from a Transaction - * - * The following fields are required in the $customer array. - * This array can be the same as supplied to processPayment() with - * the ID added. - * - * id Customer ID - could be customer type plus record number - * email Customer E-Mail address - * - * Return array - * - * customerProfileId Profile ID for created customer profile (if successful) - * paymentProfileId Profile ID for payment (if successful) - * status True if successful - * statusText Explanation of result - * - * @param $transId string Transaction ID from a completed transaction - * @param $customer array Custoemr information - * - * @return array - * - */ - public function createProfileFromTrans($transId = false, $customer = false) - { - - $resp = false; - - // Set the transaction's refId using timestamp - $refId = 'ref' . time(); + $resp = array_merge( $resp, $profileResponse ); - $errorMsg = array(); - - // Check required input - if ($transId === false || trim($transId) == '' ) { - $errorMsg[] = 'Required Transaction ID was not supplied'; - } - if (!$customer || !is_array($customer) ) { - $errorMsg[] = 'Required customer information was not supplied'; - } - if (!isset($customer['id']) || trim($customer['id']) == '' ) { -// $errorMsg[] = 'Required Customer ID was not supplied'; - } - if (strlen($customer['id']) > 20 ) { - $errorMsg[] = 'Customer ID is too long - maximum 20 characters'; - } - if (!isset($customer['email']) || trim($customer['email']) == '' ) { - $errorMsg[] = 'Required Customer E-Mail address was not supplied'; - } - - // If there's error messages - if (count($errorMsg) > 0) { - $resp = array( - 'profileId' => false, - 'profileStatus' => false, - 'profileStatusText' => implode(', ', $errorMsg) - ); - return $resp; - } - - // Build customer profile - only using customerId and E - $customerProfile = new AnetAPI\CustomerProfileBaseType(); - $customerProfile->setMerchantCustomerId($customer['id']); - $customerProfile->setEmail($customer['email']); - $customerProfile->setDescription($customer['fname'].' '.$customer['lname'].', '.$customer['city'].' '.$customer['state'].' '.$customer['zip'].' '.$customer['phone']); - - $request = new AnetAPI\CreateCustomerProfileFromTransactionRequest(); - $request->setMerchantAuthentication($this->merchantAuthentication); - $request->setTransId($transId); - $request->setCustomer($customerProfile); - $request->setRefId($refId); - - // echo "PROFILE REQUEST
".print_r($request,1)."
"; - - $controller = new AnetController\CreateCustomerProfileFromTransactionController($request); - - // Select processing environment - switch ($this->account['environment']) { - - case 'SANDBOX': - $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX); - break; - - case 'PRODUCTION': - $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::PRODUCTION); - break; - - default: - die('Authorise.Net Payment Gateway: Serious error - processing environment not specified'); - break; - - } - - // echo "PROFILE RESPONSE
".print_r($response,1)."
"; - - if ($response != null) { - - $errorMessages = $response->getMessages()->getMessage(); - - if ($response->getMessages()->getResultCode() == "Ok") { - $resp = array( - 'customerProfileId' => $response->getCustomerProfileId(), - 'paymentProfileId' => $response->getCustomerPaymentProfileIdList()[0], - 'profileStatus' => true, - 'profileStatusText' => $errorMessages[0]->getText() - ); - return $resp; - - } else { - $errorMessages = $response->getMessages()->getMessage(); - $resp = array( - 'customerProfileId' => false, - 'paymentProfileId' => false, - 'profileStatus' => false, - 'profileStatusText' => $errorMessages[0]->getText() - ); - return $resp; } } - // No valid response - $resp = array( - 'profileId' => false, - 'profileStatus' => false, - 'profileStatusText' => 'bad response' - ); return $resp; - } } -- 2.17.1