From b0888b8e061dc198a9600d872f03715c6028af0e Mon Sep 17 00:00:00 2001 From: tejas Date: Sat, 17 Nov 2018 12:38:16 +0530 Subject: [PATCH 01/99] Updated to the latest plugin files 1.1.2 --- gravity-forms-braintree.php | 2 +- lib/class.plugify-gform-braintree.php | 15 +++------------ readme.txt | 14 ++++++++------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/gravity-forms-braintree.php b/gravity-forms-braintree.php index 45534e9..5426412 100644 --- a/gravity-forms-braintree.php +++ b/gravity-forms-braintree.php @@ -4,7 +4,7 @@ Plugin URI: http://plugify.io/ Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments Author: Plugify -Version: 1.1.1 +Version: 1.1.2 Author URI: http://plugify.io */ diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 5128597..eb3dbdc 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -61,7 +61,7 @@ public function init_frontend () { * @since 1.0 * @return void */ - public function authorize( $feed, $submission_data, $form, $entry ) { + protected function authorize( $feed, $submission_data, $form, $entry ) { // Prepare authorization response payload $authorization = array( @@ -92,16 +92,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), 'cardholderName' => $submission_data['card_name'], 'cvv' => $submission_data['card_security_code'] - ), - 'customer' => array( - 'firstName' => $submission_data['card_name'] - ), - 'billing' => array( - 'firstName' => $submission_data['card_name'], - 'streetAddress' => $submission_data['address'], - 'locality' => $submission_data['city'], - 'postalCode' => $submission_data['zip'] - ) + ) ); try { @@ -171,7 +162,7 @@ public function feed_settings_fields () { $settings = parent::feed_settings_fields(); // Remove billing information - //$settings = $this->remove_field( 'billingInformation', $settings ); + $settings = $this->remove_field( 'billingInformation', $settings ); // Remove options $settings = $this->remove_field( 'options', $settings ); diff --git a/readme.txt b/readme.txt index 05daa4d..a3a02c8 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === Gravity Forms Braintree Add-On === -Contributors: Plugify, hello@lukerollans.me +Contributors: Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=hello%40plugify%2eio&lc=GB&item_name=Plugin%20Development%20Donation¤cy_code=USD Tags: credit card,braintree,gravity form,payment Requires at least: 3.8 Tested up to: 3.9 -Stable tag: 1.1.1 +Stable tag: 1.1.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -54,13 +54,15 @@ Not currently, no. This will be released very shortly in version 1.1 No filters are currently available for this pre-release version == Screenshots == -1. You will be initially greeted with the empty feed page, prompting you to configure your Braintree settings. -2. Page for configuring your Braintree settings, such as Merchant ID -3. Configuring a Gravity Forms Braintree feed -4. List of active feeds +1. Easily configure your Braintree settings, allowing for quick and efficient setup. +2. Quickly and easily configure payment feeds under Form Settings of any Gravity Form +3. List of active feeds on the current form == Changelog == += 1.1.2 = +* Internal maintenance release. Version 1.2 is coming soon and it's going to be big! + = 1.1.1 = * Dashes and spaces are now removed from credit card number before sending to Braintree From 9405170409b263a1c2b9ef54b82441168edbb4c5 Mon Sep 17 00:00:00 2001 From: tejas Date: Sat, 17 Nov 2018 12:46:27 +0530 Subject: [PATCH 02/99] remaining file to push --- lib/class.plugify-gfaddonfeedstable.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lib/class.plugify-gfaddonfeedstable.php diff --git a/lib/class.plugify-gfaddonfeedstable.php b/lib/class.plugify-gfaddonfeedstable.php new file mode 100644 index 0000000..7ccfbe3 --- /dev/null +++ b/lib/class.plugify-gfaddonfeedstable.php @@ -0,0 +1,22 @@ +", $item['id'] ); + + return $img; + + } + +} + +?> From 0389724d5c9145909966b604ad5d47a4c1c31bc8 Mon Sep 17 00:00:00 2001 From: tejas Date: Sat, 17 Nov 2018 16:24:47 +0530 Subject: [PATCH 03/99] made adjustments to the class file related to the latest library , ref #1 --- lib/class.plugify-gform-braintree.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index eb3dbdc..944b334 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -61,7 +61,7 @@ public function init_frontend () { * @since 1.0 * @return void */ - protected function authorize( $feed, $submission_data, $form, $entry ) { + public function authorize( $feed, $submission_data, $form, $entry ) { // Prepare authorization response payload $authorization = array( @@ -76,7 +76,6 @@ protected function authorize( $feed, $submission_data, $form, $entry ) { ) ); - // Perform capture in this function. For this version, we won't authorize and then capture later // at least, not in this version if( $settings = $this->get_plugin_settings() ) { @@ -110,18 +109,17 @@ protected function authorize( $feed, $submission_data, $form, $entry ) { // Send transaction to Braintree $result = Braintree_Transaction::sale( $args ); - + $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - $authorization['is_authorized'] = true; $authorization['error_message'] = ''; - $authorization['transaction_id'] = $result->transaction->_attributes['id']; + $authorization['transaction_id'] = $result->transaction->id; $authorization['captured_payment'] = array( 'is_success' => true, - 'transaction_id' => $result->transaction->_attributes['id'], - 'amount' => $result->transaction->_attributes['amount'], + 'transaction_id' => $result->transaction->id, + 'amount' => $result->transaction->amount, 'error_message' => '', 'payment_method' => 'Credit Card' ); @@ -131,8 +129,8 @@ protected function authorize( $feed, $submission_data, $form, $entry ) { // Append gateway response text to error message if it exists. If it doesn't exist, a more hardcore // failure has occured and it won't do the user any good to see it other than a general error message - if( isset( $result->_attributes['transaction']->_attributes['processorResponseText'] ) ) { - $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->_attributes['transaction']->_attributes['processorResponseText'] ); + if( isset( $result->transaction->processorResponseText ) ) { + $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); } } From 8b92e7857a45290531c4d5dbf6372cc03656bfd5 Mon Sep 17 00:00:00 2001 From: tejas Date: Sat, 17 Nov 2018 16:26:10 +0530 Subject: [PATCH 04/99] updated the latest library files of Braintree, ref #1 --- lib/Braintree.php | 181 +---- lib/Braintree/AccountUpdaterDailyReport.php | 43 ++ lib/Braintree/AchMandate.php | 55 ++ lib/Braintree/AddOn.php | 33 +- lib/Braintree/AddOnGateway.php | 53 ++ lib/Braintree/Address.php | 314 ++------ lib/Braintree/AddressGateway.php | 314 ++++++++ lib/Braintree/AmexExpressCheckoutCard.php | 79 ++ lib/Braintree/AndroidPayCard.php | 89 +++ lib/Braintree/ApplePayCard.php | 100 +++ lib/Braintree/ApplePayGateway.php | 65 ++ lib/Braintree/ApplePayOptions.php | 28 + lib/Braintree/AuthorizationAdjustment.php | 35 + lib/Braintree/Base.php | 88 +++ lib/Braintree/BinData.php | 30 + lib/Braintree/ClientToken.php | 49 ++ lib/Braintree/ClientTokenGateway.php | 129 ++++ lib/Braintree/CoinbaseAccount.php | 110 +++ lib/Braintree/Collection.php | 24 +- lib/Braintree/Configuration.php | 615 ++++++++++++---- .../ConnectedMerchantPayPalStatusChanged.php | 37 + .../ConnectedMerchantStatusTransitioned.php | 37 + lib/Braintree/CredentialsParser.php | 147 ++++ lib/Braintree/CreditCard.php | 571 ++++----------- lib/Braintree/CreditCardGateway.php | 486 ++++++++++++ lib/Braintree/CreditCardVerification.php | 50 +- .../CreditCardVerificationGateway.php | 74 ++ .../CreditCardVerificationSearch.php | 75 +- lib/Braintree/Customer.php | 566 ++++++-------- lib/Braintree/CustomerGateway.php | 662 +++++++++++++++++ lib/Braintree/CustomerSearch.php | 52 +- lib/Braintree/Descriptor.php | 5 +- lib/Braintree/Digest.php | 29 +- lib/Braintree/Disbursement.php | 37 +- lib/Braintree/DisbursementDetails.php | 17 +- lib/Braintree/Discount.php | 25 +- lib/Braintree/DiscountGateway.php | 31 + lib/Braintree/Dispute.php | 177 +++++ lib/Braintree/Dispute/EvidenceDetails.php | 31 + .../Dispute/StatusHistoryDetails.php | 20 + lib/Braintree/Dispute/TransactionDetails.php | 25 + lib/Braintree/DisputeGateway.php | 274 +++++++ lib/Braintree/DisputeSearch.php | 90 +++ lib/Braintree/DocumentUpload.php | 45 ++ lib/Braintree/DocumentUploadGateway.php | 81 ++ lib/Braintree/EndsWithNode.php | 23 + lib/Braintree/EqualityNode.php | 4 +- lib/Braintree/Error/Codes.php | 678 ++++++++++++----- lib/Braintree/Error/ErrorCollection.php | 37 +- lib/Braintree/Error/Validation.php | 26 +- .../Error/ValidationErrorCollection.php | 30 +- lib/Braintree/EuropeBankAccount.php | 67 ++ lib/Braintree/Exception.php | 13 +- lib/Braintree/Exception/Authentication.php | 16 +- lib/Braintree/Exception/Authorization.php | 14 +- lib/Braintree/Exception/Configuration.php | 15 +- lib/Braintree/Exception/Connection.php | 17 + .../Exception/DownForMaintenance.php | 14 +- lib/Braintree/Exception/ForgedQueryString.php | 17 +- lib/Braintree/Exception/InvalidChallenge.php | 9 + lib/Braintree/Exception/InvalidSignature.php | 8 +- lib/Braintree/Exception/NotFound.php | 14 +- lib/Braintree/Exception/SSLCaFileNotFound.php | 14 +- lib/Braintree/Exception/SSLCertificate.php | 14 +- lib/Braintree/Exception/ServerError.php | 14 +- .../TestOperationPerformedInProduction.php | 15 + lib/Braintree/Exception/Timeout.php | 16 + lib/Braintree/Exception/TooManyRequests.php | 16 + lib/Braintree/Exception/Unexpected.php | 14 +- lib/Braintree/Exception/UpgradeRequired.php | 8 +- lib/Braintree/Exception/ValidationsFailed.php | 14 +- lib/Braintree/FacilitatedDetails.php | 29 + lib/Braintree/FacilitatorDetails.php | 30 + lib/Braintree/Gateway.php | 278 +++++++ .../GrantedPaymentInstrumentUpdate.php | 73 ++ lib/Braintree/GraphQL.php | 44 ++ lib/Braintree/Http.php | 267 +++++-- lib/Braintree/IbanBankAccount.php | 57 ++ lib/Braintree/IdealPayment.php | 92 +++ lib/Braintree/IdealPaymentGateway.php | 104 +++ lib/Braintree/Instance.php | 31 +- lib/Braintree/IsNode.php | 13 +- lib/Braintree/KeyValueNode.php | 11 +- lib/Braintree/LocalPaymentCompleted.php | 68 ++ lib/Braintree/MasterpassCard.php | 141 ++++ lib/Braintree/Merchant.php | 36 + lib/Braintree/MerchantAccount.php | 162 +--- .../MerchantAccount/AddressDetails.php | 9 +- .../MerchantAccount/BusinessDetails.php | 8 +- .../MerchantAccount/FundingDetails.php | 8 +- .../MerchantAccount/IndividualDetails.php | 8 +- lib/Braintree/MerchantAccountGateway.php | 182 +++++ lib/Braintree/MerchantGateway.php | 42 ++ lib/Braintree/Modification.php | 17 +- lib/Braintree/MultipleValueNode.php | 18 +- lib/Braintree/MultipleValueOrTextNode.php | 20 +- lib/Braintree/OAuthAccessRevocation.php | 32 + lib/Braintree/OAuthCredentials.php | 34 + lib/Braintree/OAuthGateway.php | 124 ++++ lib/Braintree/OAuthResult.php | 34 + lib/Braintree/PaginatedCollection.php | 120 +++ lib/Braintree/PaginatedResult.php | 32 + lib/Braintree/PartialMatchNode.php | 8 +- lib/Braintree/PartnerMerchant.php | 15 +- lib/Braintree/PayPalAccount.php | 109 +++ lib/Braintree/PayPalAccountGateway.php | 178 +++++ lib/Braintree/PaymentInstrumentType.php | 19 + lib/Braintree/PaymentMethod.php | 44 ++ lib/Braintree/PaymentMethodGateway.php | 363 +++++++++ lib/Braintree/PaymentMethodNonce.php | 56 ++ lib/Braintree/PaymentMethodNonceGateway.php | 64 ++ lib/Braintree/Plan.php | 40 +- lib/Braintree/PlanGateway.php | 34 + lib/Braintree/RangeNode.php | 18 +- lib/Braintree/ResourceCollection.php | 50 +- .../Result/CreditCardVerification.php | 40 +- lib/Braintree/Result/Error.php | 58 +- lib/Braintree/Result/Successful.php | 66 +- .../Result/UsBankAccountVerification.php | 112 +++ lib/Braintree/RiskData.php | 30 + lib/Braintree/SamsungPayCard.php | 138 ++++ lib/Braintree/SettlementBatchSummary.php | 75 +- .../SettlementBatchSummaryGateway.php | 106 +++ lib/Braintree/SignatureService.php | 24 + lib/Braintree/Subscription.php | 260 ++----- lib/Braintree/Subscription/StatusDetails.php | 24 + lib/Braintree/SubscriptionGateway.php | 226 ++++++ lib/Braintree/SubscriptionSearch.php | 66 +- lib/Braintree/Test/CreditCardNumbers.php | 62 +- lib/Braintree/Test/MerchantAccount.php | 6 +- lib/Braintree/Test/Nonces.php | 80 ++ lib/Braintree/Test/Transaction.php | 62 ++ lib/Braintree/Test/TransactionAmounts.php | 12 +- lib/Braintree/Test/VenmoSdk.php | 6 +- lib/Braintree/TestingGateway.php | 52 ++ lib/Braintree/TextNode.php | 6 +- lib/Braintree/ThreeDSecureInfo.php | 30 + lib/Braintree/Transaction.php | 691 +++++++----------- lib/Braintree/Transaction/AddressDetails.php | 17 +- .../AmexExpressCheckoutCardDetails.php | 43 ++ .../Transaction/AndroidPayCardDetails.php | 47 ++ .../Transaction/ApplePayCardDetails.php | 39 + lib/Braintree/Transaction/CoinbaseDetails.php | 38 + .../Transaction/CreditCardDetails.php | 20 +- lib/Braintree/Transaction/CustomerDetails.php | 16 +- .../Transaction/EuropeBankAccountDetails.php | 24 + .../Transaction/IdealPaymentDetails.php | 23 + lib/Braintree/Transaction/LineItem.php | 4 + .../Transaction/MasterpassCardDetails.php | 51 ++ lib/Braintree/Transaction/PayPalDetails.php | 41 ++ .../Transaction/SamsungPayCardDetails.php | 52 ++ lib/Braintree/Transaction/StatusDetails.php | 26 +- .../Transaction/SubscriptionDetails.php | 15 +- .../Transaction/UsBankAccountDetails.php | 40 + .../Transaction/VenmoAccountDetails.php | 38 + .../Transaction/VisaCheckoutCardDetails.php | 52 ++ lib/Braintree/TransactionGateway.php | 550 ++++++++++++++ lib/Braintree/TransactionLineItem.php | 54 ++ lib/Braintree/TransactionLineItemGateway.php | 67 ++ lib/Braintree/TransactionSearch.php | 214 +++--- lib/Braintree/TransparentRedirect.php | 259 +------ lib/Braintree/TransparentRedirectGateway.php | 289 ++++++++ lib/Braintree/UnknownPaymentMethod.php | 69 ++ lib/Braintree/UsBankAccount.php | 117 +++ lib/Braintree/UsBankAccountGateway.php | 106 +++ lib/Braintree/UsBankAccountVerification.php | 102 +++ .../UsBankAccountVerificationGateway.php | 129 ++++ .../UsBankAccountVerificationSearch.php | 64 ++ lib/Braintree/Util.php | 334 ++++++--- lib/Braintree/VenmoAccount.php | 74 ++ lib/Braintree/Version.php | 19 +- lib/Braintree/VisaCheckoutCard.php | 154 ++++ lib/Braintree/WebhookNotification.php | 109 +-- lib/Braintree/WebhookNotificationGateway.php | 77 ++ lib/Braintree/WebhookTesting.php | 218 +----- lib/Braintree/WebhookTestingGateway.php | 553 ++++++++++++++ lib/Braintree/Xml.php | 16 +- lib/Braintree/Xml/Generator.php | 41 +- lib/Braintree/Xml/Parser.php | 225 +++--- lib/autoload.php | 21 + lib/ssl/api_braintreegateway_com.ca.crt | 336 +++------ 181 files changed, 13259 insertions(+), 4083 deletions(-) create mode 100644 lib/Braintree/AccountUpdaterDailyReport.php create mode 100644 lib/Braintree/AchMandate.php create mode 100644 lib/Braintree/AddOnGateway.php create mode 100644 lib/Braintree/AddressGateway.php create mode 100644 lib/Braintree/AmexExpressCheckoutCard.php create mode 100644 lib/Braintree/AndroidPayCard.php create mode 100644 lib/Braintree/ApplePayCard.php create mode 100644 lib/Braintree/ApplePayGateway.php create mode 100644 lib/Braintree/ApplePayOptions.php create mode 100644 lib/Braintree/AuthorizationAdjustment.php create mode 100644 lib/Braintree/Base.php create mode 100644 lib/Braintree/BinData.php create mode 100644 lib/Braintree/ClientToken.php create mode 100644 lib/Braintree/ClientTokenGateway.php create mode 100644 lib/Braintree/CoinbaseAccount.php create mode 100644 lib/Braintree/ConnectedMerchantPayPalStatusChanged.php create mode 100644 lib/Braintree/ConnectedMerchantStatusTransitioned.php create mode 100644 lib/Braintree/CredentialsParser.php create mode 100644 lib/Braintree/CreditCardGateway.php create mode 100644 lib/Braintree/CreditCardVerificationGateway.php create mode 100644 lib/Braintree/CustomerGateway.php create mode 100644 lib/Braintree/DiscountGateway.php create mode 100644 lib/Braintree/Dispute.php create mode 100644 lib/Braintree/Dispute/EvidenceDetails.php create mode 100644 lib/Braintree/Dispute/StatusHistoryDetails.php create mode 100644 lib/Braintree/Dispute/TransactionDetails.php create mode 100644 lib/Braintree/DisputeGateway.php create mode 100644 lib/Braintree/DisputeSearch.php create mode 100644 lib/Braintree/DocumentUpload.php create mode 100644 lib/Braintree/DocumentUploadGateway.php create mode 100644 lib/Braintree/EndsWithNode.php create mode 100644 lib/Braintree/EuropeBankAccount.php create mode 100644 lib/Braintree/Exception/Connection.php create mode 100644 lib/Braintree/Exception/InvalidChallenge.php create mode 100644 lib/Braintree/Exception/TestOperationPerformedInProduction.php create mode 100644 lib/Braintree/Exception/Timeout.php create mode 100644 lib/Braintree/Exception/TooManyRequests.php create mode 100644 lib/Braintree/FacilitatedDetails.php create mode 100644 lib/Braintree/FacilitatorDetails.php create mode 100644 lib/Braintree/Gateway.php create mode 100644 lib/Braintree/GrantedPaymentInstrumentUpdate.php create mode 100644 lib/Braintree/GraphQL.php create mode 100644 lib/Braintree/IbanBankAccount.php create mode 100644 lib/Braintree/IdealPayment.php create mode 100644 lib/Braintree/IdealPaymentGateway.php create mode 100644 lib/Braintree/LocalPaymentCompleted.php create mode 100644 lib/Braintree/MasterpassCard.php create mode 100644 lib/Braintree/Merchant.php create mode 100644 lib/Braintree/MerchantAccountGateway.php create mode 100644 lib/Braintree/MerchantGateway.php create mode 100644 lib/Braintree/OAuthAccessRevocation.php create mode 100644 lib/Braintree/OAuthCredentials.php create mode 100644 lib/Braintree/OAuthGateway.php create mode 100644 lib/Braintree/OAuthResult.php create mode 100644 lib/Braintree/PaginatedCollection.php create mode 100644 lib/Braintree/PaginatedResult.php create mode 100644 lib/Braintree/PayPalAccount.php create mode 100644 lib/Braintree/PayPalAccountGateway.php create mode 100644 lib/Braintree/PaymentInstrumentType.php create mode 100644 lib/Braintree/PaymentMethod.php create mode 100644 lib/Braintree/PaymentMethodGateway.php create mode 100644 lib/Braintree/PaymentMethodNonce.php create mode 100644 lib/Braintree/PaymentMethodNonceGateway.php create mode 100644 lib/Braintree/PlanGateway.php create mode 100644 lib/Braintree/Result/UsBankAccountVerification.php create mode 100644 lib/Braintree/RiskData.php create mode 100644 lib/Braintree/SamsungPayCard.php create mode 100644 lib/Braintree/SettlementBatchSummaryGateway.php create mode 100644 lib/Braintree/SignatureService.php create mode 100644 lib/Braintree/Subscription/StatusDetails.php create mode 100644 lib/Braintree/SubscriptionGateway.php create mode 100644 lib/Braintree/Test/Nonces.php create mode 100644 lib/Braintree/Test/Transaction.php create mode 100644 lib/Braintree/TestingGateway.php create mode 100644 lib/Braintree/ThreeDSecureInfo.php create mode 100644 lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php create mode 100644 lib/Braintree/Transaction/AndroidPayCardDetails.php create mode 100644 lib/Braintree/Transaction/ApplePayCardDetails.php create mode 100644 lib/Braintree/Transaction/CoinbaseDetails.php create mode 100644 lib/Braintree/Transaction/EuropeBankAccountDetails.php create mode 100644 lib/Braintree/Transaction/IdealPaymentDetails.php create mode 100644 lib/Braintree/Transaction/LineItem.php create mode 100644 lib/Braintree/Transaction/MasterpassCardDetails.php create mode 100644 lib/Braintree/Transaction/PayPalDetails.php create mode 100644 lib/Braintree/Transaction/SamsungPayCardDetails.php create mode 100644 lib/Braintree/Transaction/UsBankAccountDetails.php create mode 100644 lib/Braintree/Transaction/VenmoAccountDetails.php create mode 100644 lib/Braintree/Transaction/VisaCheckoutCardDetails.php create mode 100644 lib/Braintree/TransactionGateway.php create mode 100644 lib/Braintree/TransactionLineItem.php create mode 100644 lib/Braintree/TransactionLineItemGateway.php create mode 100644 lib/Braintree/TransparentRedirectGateway.php create mode 100644 lib/Braintree/UnknownPaymentMethod.php create mode 100644 lib/Braintree/UsBankAccount.php create mode 100644 lib/Braintree/UsBankAccountGateway.php create mode 100644 lib/Braintree/UsBankAccountVerification.php create mode 100644 lib/Braintree/UsBankAccountVerificationGateway.php create mode 100644 lib/Braintree/UsBankAccountVerificationSearch.php create mode 100644 lib/Braintree/VenmoAccount.php create mode 100644 lib/Braintree/VisaCheckoutCard.php create mode 100644 lib/Braintree/WebhookNotificationGateway.php create mode 100644 lib/Braintree/WebhookTestingGateway.php create mode 100644 lib/autoload.php diff --git a/lib/Braintree.php b/lib/Braintree.php index e940d65..066107a 100644 --- a/lib/Braintree.php +++ b/lib/Braintree.php @@ -1,181 +1,24 @@ _attributes)) { - return $this->_attributes[$name]; - } - else { - trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE); - return null; - } - } - - /** - * used by isset() and empty() - * @access public - * @param string $name property name - * @return boolean - */ - public function __isset($name) - { - return array_key_exists($name, $this->_attributes); - } - - public function _set($key, $value) - { - $this->_attributes[$key] = $value; - } - /** - * - * @param string $className - * @param object $resultObj - * @return object returns the passed object if successful - * @throws Braintree_Exception_ValidationsFailed - */ - public static function returnObjectOrThrowException($className, $resultObj) - { - $resultObjName = Braintree_Util::cleanClassName($className); - if ($resultObj->success) { - return $resultObj->$resultObjName; - } else { - throw new Braintree_Exception_ValidationsFailed(); - } - } -} -require_once('Braintree/Modification.php'); -require_once('Braintree/Instance.php'); +require_once(__DIR__ . DIRECTORY_SEPARATOR . 'autoload.php'); -require_once('Braintree/Address.php'); -require_once('Braintree/AddOn.php'); -require_once('Braintree/Collection.php'); -require_once('Braintree/Configuration.php'); -require_once('Braintree/CreditCard.php'); -require_once('Braintree/Customer.php'); -require_once('Braintree/CustomerSearch.php'); -require_once('Braintree/DisbursementDetails.php'); -require_once('Braintree/Descriptor.php'); -require_once('Braintree/Digest.php'); -require_once('Braintree/Discount.php'); -require_once('Braintree/IsNode.php'); -require_once('Braintree/EqualityNode.php'); -require_once('Braintree/Exception.php'); -require_once('Braintree/Http.php'); -require_once('Braintree/KeyValueNode.php'); -require_once('Braintree/MerchantAccount.php'); -require_once('Braintree/MerchantAccount/BusinessDetails.php'); -require_once('Braintree/MerchantAccount/FundingDetails.php'); -require_once('Braintree/MerchantAccount/IndividualDetails.php'); -require_once('Braintree/MerchantAccount/AddressDetails.php'); -require_once('Braintree/MultipleValueNode.php'); -require_once('Braintree/MultipleValueOrTextNode.php'); -require_once('Braintree/PartialMatchNode.php'); -require_once('Braintree/Plan.php'); -require_once('Braintree/RangeNode.php'); -require_once('Braintree/ResourceCollection.php'); -require_once('Braintree/SettlementBatchSummary.php'); -require_once('Braintree/Subscription.php'); -require_once('Braintree/SubscriptionSearch.php'); -require_once('Braintree/TextNode.php'); -require_once('Braintree/Transaction.php'); -require_once('Braintree/Disbursement.php'); -require_once('Braintree/TransactionSearch.php'); -require_once('Braintree/TransparentRedirect.php'); -require_once('Braintree/Util.php'); -require_once('Braintree/Version.php'); -require_once('Braintree/Xml.php'); -require_once('Braintree/Error/Codes.php'); -require_once('Braintree/Error/ErrorCollection.php'); -require_once('Braintree/Error/Validation.php'); -require_once('Braintree/Error/ValidationErrorCollection.php'); -require_once('Braintree/Exception/Authentication.php'); -require_once('Braintree/Exception/Authorization.php'); -require_once('Braintree/Exception/Configuration.php'); -require_once('Braintree/Exception/DownForMaintenance.php'); -require_once('Braintree/Exception/ForgedQueryString.php'); -require_once('Braintree/Exception/InvalidSignature.php'); -require_once('Braintree/Exception/NotFound.php'); -require_once('Braintree/Exception/ServerError.php'); -require_once('Braintree/Exception/SSLCertificate.php'); -require_once('Braintree/Exception/SSLCaFileNotFound.php'); -require_once('Braintree/Exception/Unexpected.php'); -require_once('Braintree/Exception/UpgradeRequired.php'); -require_once('Braintree/Exception/ValidationsFailed.php'); -require_once('Braintree/Result/CreditCardVerification.php'); -require_once('Braintree/Result/Error.php'); -require_once('Braintree/Result/Successful.php'); -require_once('Braintree/Test/CreditCardNumbers.php'); -require_once('Braintree/Test/MerchantAccount.php'); -require_once('Braintree/Test/TransactionAmounts.php'); -require_once('Braintree/Test/VenmoSdk.php'); -require_once('Braintree/Transaction/AddressDetails.php'); -require_once('Braintree/Transaction/CreditCardDetails.php'); -require_once('Braintree/Transaction/CustomerDetails.php'); -require_once('Braintree/Transaction/StatusDetails.php'); -require_once('Braintree/Transaction/SubscriptionDetails.php'); -require_once('Braintree/WebhookNotification.php'); -require_once('Braintree/WebhookTesting.php'); -require_once('Braintree/Xml/Generator.php'); -require_once('Braintree/Xml/Parser.php'); -require_once('Braintree/CreditCardVerification.php'); -require_once('Braintree/CreditCardVerificationSearch.php'); -require_once('Braintree/PartnerMerchant.php'); - -if (version_compare(PHP_VERSION, '5.2.1', '<')) { - throw new Braintree_Exception('PHP version >= 5.2.1 required'); +if (version_compare(PHP_VERSION, '5.4.0', '<')) { + throw new Braintree_Exception('PHP version >= 5.4.0 required'); } - -function requireDependencies() { - $requiredExtensions = array('xmlwriter', 'SimpleXML', 'openssl', 'dom', 'hash', 'curl'); - foreach ($requiredExtensions AS $ext) { - if (!extension_loaded($ext)) { - throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.'); +class Braintree { + public static function requireDependencies() { + $requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl']; + foreach ($requiredExtensions AS $ext) { + if (!extension_loaded($ext)) { + throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.'); + } } } } -requireDependencies(); +Braintree::requireDependencies(); diff --git a/lib/Braintree/AccountUpdaterDailyReport.php b/lib/Braintree/AccountUpdaterDailyReport.php new file mode 100644 index 0000000..226bdfe --- /dev/null +++ b/lib/Braintree/AccountUpdaterDailyReport.php @@ -0,0 +1,43 @@ +_attributes = $disputeAttribs; + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + public function __toString() + { + $display = [ + 'reportDate', 'reportUrl' + ]; + + $displayAttributes = []; + foreach ($display AS $attrib) { + $displayAttributes[$attrib] = $this->$attrib; + } + return __CLASS__ . '[' . + Util::attributesToString($displayAttributes) .']'; + } +} +class_alias('Braintree\AccountUpdaterDailyReport', 'Braintree_AccountUpdaterDailyReport'); diff --git a/lib/Braintree/AchMandate.php b/lib/Braintree/AchMandate.php new file mode 100644 index 0000000..86eeea6 --- /dev/null +++ b/lib/Braintree/AchMandate.php @@ -0,0 +1,55 @@ +_attributes) . ']'; + } + + /** + * sets instance properties from an array of values + * + * @ignore + * @access protected + * @param array $achAttribs array of achMandate data + * @return void + */ + protected function _initialize($achAttribs) + { + // set the attributes + $this->_attributes = $achAttribs; + } + + /** + * factory method: returns an instance of AchMandate + * to the requesting method, with populated properties + * @ignore + * @return AchMandate + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + + } +} +class_alias('Braintree\AchMandate', 'Braintree_Mandate'); diff --git a/lib/Braintree/AddOn.php b/lib/Braintree/AddOn.php index 98a4c47..04c1705 100644 --- a/lib/Braintree/AddOn.php +++ b/lib/Braintree/AddOn.php @@ -1,22 +1,29 @@ $response['addOns']); - - return Braintree_Util::extractAttributeAsArray( - $addOns, - 'addOn' - ); - } +namespace Braintree; +class AddOn extends Modification +{ + /** + * + * @param array $attributes + * @return AddOn + */ public static function factory($attributes) { $instance = new self(); $instance->_initialize($attributes); return $instance; } + + + /** + * static methods redirecting to gateway + * + * @return AddOn[] + */ + public static function all() + { + return Configuration::gateway()->addOn()->all(); + } } +class_alias('Braintree\AddOn', 'Braintree_AddOn'); diff --git a/lib/Braintree/AddOnGateway.php b/lib/Braintree/AddOnGateway.php new file mode 100644 index 0000000..9ecf942 --- /dev/null +++ b/lib/Braintree/AddOnGateway.php @@ -0,0 +1,53 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /** + * + * @return AddOn[] + */ + public function all() + { + $path = $this->_config->merchantPath() . '/add_ons'; + $response = $this->_http->get($path); + + $addOns = ["addOn" => $response['addOns']]; + + return Util::extractAttributeAsArray( + $addOns, + 'addOn' + ); + } +} +class_alias('Braintree\AddOnGateway', 'Braintree_AddOnGateway'); diff --git a/lib/Braintree/Address.php b/lib/Braintree/Address.php index 821959d..7b6920e 100644 --- a/lib/Braintree/Address.php +++ b/lib/Braintree/Address.php @@ -1,13 +1,9 @@ $attribs) - ); - } - /** - * attempts the create operation assuming all data will validate - * returns a Braintree_Address object instead of a Result - * - * @access public - * @param array $attribs - * @return object - * @throws Braintree_Exception_ValidationError - */ - public static function createNoValidate($attribs) - { - $result = self::create($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); - - } - - /** - * delete an address by id - * - * @param mixed $customerOrId - * @param string $addressId - */ - public static function delete($customerOrId = null, $addressId = null) - { - self::_validateId($addressId); - $customerId = self::_determineCustomerId($customerOrId); - Braintree_Http::delete( - '/customers/' . $customerId . '/addresses/' . $addressId - ); - return new Braintree_Result_Successful(); - } - - /** - * find an address by id - * - * Finds the address with the given addressId that is associated - * to the given customerOrId. - * If the address cannot be found, a NotFound exception will be thrown. - * - * - * @access public - * @param mixed $customerOrId - * @param string $addressId - * @return object Braintree_Address - * @throws Braintree_Exception_NotFound - */ - public static function find($customerOrId, $addressId) - { - - $customerId = self::_determineCustomerId($customerOrId); - self::_validateId($addressId); - - try { - $response = Braintree_Http::get( - '/customers/' . $customerId . '/addresses/' . $addressId - ); - return self::factory($response['address']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound( - 'address for customer ' . $customerId . - ' with id ' . $addressId . ' not found.' - ); - } - - } - - /** - * returns false if comparing object is not a Braintree_Address, - * or is a Braintree_Address with a different id + * returns false if comparing object is not a Address, + * or is a Address with a different id * * @param object $other address to compare against * @return boolean */ public function isEqual($other) { - return !($other instanceof Braintree_Address) ? + return !($other instanceof self) ? false : ($this->id === $other->id && $this->customerId === $other->customerId); } - /** - * updates the address record - * - * if calling this method in static context, - * customerOrId is the 2nd attribute, addressId 3rd. - * customerOrId & addressId are not sent in object context. - * - * - * @access public - * @param array $attributes - * @param mixed $customerOrId (only used in static call) - * @param string $addressId (only used in static call) - * @return object Braintree_Result_Successful or Braintree_Result_Error - */ - public static function update($customerOrId, $addressId, $attributes) - { - self::_validateId($addressId); - $customerId = self::_determineCustomerId($customerOrId); - Braintree_Util::verifyKeys(self::updateSignature(), $attributes); - - $response = Braintree_Http::put( - '/customers/' . $customerId . '/addresses/' . $addressId, - array('address' => $attributes) - ); - - return self::_verifyGatewayResponse($response); - - } - - /** - * update an address record, assuming validations will pass - * - * if calling this method in static context, - * customerOrId is the 2nd attribute, addressId 3rd. - * customerOrId & addressId are not sent in object context. - * - * @access public - * @param array $transactionAttribs - * @param string $customerId - * @return object Braintree_Transaction - * @throws Braintree_Exception_ValidationsFailed - * @see Braintree_Address::update() - */ - public static function updateNoValidate($customerOrId, $addressId, $attributes) - { - $result = self::update($customerOrId, $addressId, $attributes); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - - /** - * creates a full array signature of a valid create request - * @return array gateway create request format - */ - public static function createSignature() - { - return array( - 'company', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', - 'countryName', 'customerId', 'extendedAddress', 'firstName', - 'lastName', 'locality', 'postalCode', 'region', 'streetAddress' - ); - } - - /** - * creates a full array signature of a valid update request - * @return array gateway update request format - */ - public static function updateSignature() - { - // TODO: remove customerId from update signature - return self::createSignature(); - - } - /** * create a printable representation of the object as: * ClassName[property=value, property=value] * @ignore - * @return var + * @return string */ public function __toString() { return __CLASS__ . '[' . - Braintree_Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** @@ -227,7 +60,7 @@ public function __toString() * @ignore * @access protected * @param array $addressAttribs array of address data - * @return none + * @return void */ protected function _initialize($addressAttribs) { @@ -236,117 +69,82 @@ protected function _initialize($addressAttribs) } /** - * verifies that a valid address id is being used + * factory method: returns an instance of Address + * to the requesting method, with populated properties * @ignore - * @param string $id address id - * @throws InvalidArgumentException + * @return Address */ - private static function _validateId($id = null) + public static function factory($attributes) { - if (empty($id) || trim($id) == "") { - throw new InvalidArgumentException( - 'expected address id to be set' - ); - } - if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid address id.' - ); - } + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + // static methods redirecting to gateway + /** - * verifies that a valid customer id is being used - * @ignore - * @param string $id customer id - * @throws InvalidArgumentException + * + * @param array $attribs + * @return Address */ - private static function _validateCustomerId($id = null) + public static function create($attribs) { - if (empty($id) || trim($id) == "") { - throw new InvalidArgumentException( - 'expected customer id to be set' - ); - } - if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid customer id.' - ); - } - + return Configuration::gateway()->address()->create($attribs); } /** - * determines if a string id or Customer object was passed - * @ignore - * @param mixed $customerOrId - * @return string customerId + * + * @param array $attribs + * @return Address */ - private static function _determineCustomerId($customerOrId) + public static function createNoValidate($attribs) { - $customerId = ($customerOrId instanceof Braintree_Customer) ? $customerOrId->id : $customerOrId; - self::_validateCustomerId($customerId); - return $customerId; - + return Configuration::gateway()->address()->createNoValidate($attribs); } - /* private class methods */ /** - * sends the create request to the gateway - * @ignore - * @param string $url - * @param array $params - * @return mixed + * + * @param Customer|int $customerOrId + * @param int $addressId + * @throws InvalidArgumentException + * @return Result\Successful */ - private static function _doCreate($url, $params) + public static function delete($customerOrId = null, $addressId = null) { - $response = Braintree_Http::post($url, $params); - - return self::_verifyGatewayResponse($response); - + return Configuration::gateway()->address()->delete($customerOrId, $addressId); } /** - * generic method for validating incoming gateway responses - * - * creates a new Braintree_Address object and encapsulates - * it inside a Braintree_Result_Successful object, or - * encapsulates a Braintree_Errors object inside a Result_Error - * alternatively, throws an Unexpected exception if the response is invalid. * - * @ignore - * @param array $response gateway response values - * @return object Result_Successful or Result_Error - * @throws Braintree_Exception_Unexpected + * @param Customer|int $customerOrId + * @param int $addressId + * @throws Exception\NotFound + * @return Address */ - private static function _verifyGatewayResponse($response) + public static function find($customerOrId, $addressId) { - if (isset($response['address'])) { - // return a populated instance of Braintree_Address - return new Braintree_Result_Successful( - self::factory($response['address']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected address or apiErrorResponse" - ); - } - + return Configuration::gateway()->address()->find($customerOrId, $addressId); } /** - * factory method: returns an instance of Braintree_Address - * to the requesting method, with populated properties - * @ignore - * @return object instance of Braintree_Address + * + * @param Customer|int $customerOrId + * @param int $addressId + * @param array $attributes + * @throws Exception\Unexpected + * @return Result\Successful|Result\Error */ - public static function factory($attributes) + public static function update($customerOrId, $addressId, $attributes) { - $instance = new self(); - $instance->_initialize($attributes); - return $instance; + return Configuration::gateway()->address()->update($customerOrId, $addressId, $attributes); + } + public static function updateNoValidate($customerOrId, $addressId, $attributes) + { + return Configuration::gateway()->address()->updateNoValidate($customerOrId, $addressId, $attributes); } } +class_alias('Braintree\Address', 'Braintree_Address'); diff --git a/lib/Braintree/AddressGateway.php b/lib/Braintree/AddressGateway.php new file mode 100644 index 0000000..a0256c0 --- /dev/null +++ b/lib/Braintree/AddressGateway.php @@ -0,0 +1,314 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + + /* public class methods */ + /** + * + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function create($attribs) + { + Util::verifyKeys(self::createSignature(), $attribs); + $customerId = isset($attribs['customerId']) ? + $attribs['customerId'] : + null; + + $this->_validateCustomerId($customerId); + unset($attribs['customerId']); + try { + return $this->_doCreate( + '/customers/' . $customerId . '/addresses', + ['address' => $attribs] + ); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'Customer ' . $customerId . ' not found.' + ); + } + } + + /** + * attempts the create operation assuming all data will validate + * returns a Address object instead of a Result + * + * @access public + * @param array $attribs + * @return self + * @throws Exception\ValidationError + */ + public function createNoValidate($attribs) + { + $result = $this->create($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + + } + + /** + * delete an address by id + * + * @param mixed $customerOrId + * @param string $addressId + */ + public function delete($customerOrId = null, $addressId = null) + { + $this->_validateId($addressId); + $customerId = $this->_determineCustomerId($customerOrId); + $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId; + $this->_http->delete($path); + return new Result\Successful(); + } + + /** + * find an address by id + * + * Finds the address with the given addressId that is associated + * to the given customerOrId. + * If the address cannot be found, a NotFound exception will be thrown. + * + * + * @access public + * @param mixed $customerOrId + * @param string $addressId + * @return Address + * @throws Exception\NotFound + */ + public function find($customerOrId, $addressId) + { + + $customerId = $this->_determineCustomerId($customerOrId); + $this->_validateId($addressId); + + try { + $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId; + $response = $this->_http->get($path); + return Address::factory($response['address']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'address for customer ' . $customerId . + ' with id ' . $addressId . ' not found.' + ); + } + + } + + /** + * updates the address record + * + * if calling this method in context, + * customerOrId is the 2nd attribute, addressId 3rd. + * customerOrId & addressId are not sent in object context. + * + * + * @access public + * @param array $attributes + * @param mixed $customerOrId (only used in call) + * @param string $addressId (only used in call) + * @return Result\Successful|Result\Error + */ + public function update($customerOrId, $addressId, $attributes) + { + $this->_validateId($addressId); + $customerId = $this->_determineCustomerId($customerOrId); + Util::verifyKeys(self::updateSignature(), $attributes); + + $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId; + $response = $this->_http->put($path, ['address' => $attributes]); + + return $this->_verifyGatewayResponse($response); + + } + + /** + * update an address record, assuming validations will pass + * + * if calling this method in context, + * customerOrId is the 2nd attribute, addressId 3rd. + * customerOrId & addressId are not sent in object context. + * + * @access public + * @param array $transactionAttribs + * @param string $customerId + * @return Transaction + * @throws Exception\ValidationsFailed + * @see Address::update() + */ + public function updateNoValidate($customerOrId, $addressId, $attributes) + { + $result = $this->update($customerOrId, $addressId, $attributes); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + + /** + * creates a full array signature of a valid create request + * @return array gateway create request format + */ + public static function createSignature() + { + return [ + 'company', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'countryName', 'customerId', 'extendedAddress', 'firstName', + 'lastName', 'locality', 'postalCode', 'region', 'streetAddress' + ]; + } + + /** + * creates a full array signature of a valid update request + * @return array gateway update request format + */ + public static function updateSignature() + { + // TODO: remove customerId from update signature + return self::createSignature(); + + } + + /** + * verifies that a valid address id is being used + * @ignore + * @param string $id address id + * @throws InvalidArgumentException + */ + private function _validateId($id = null) + { + if (empty($id) || trim($id) == "") { + throw new InvalidArgumentException( + 'expected address id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { + throw new InvalidArgumentException( + $id . ' is an invalid address id.' + ); + } + } + + /** + * verifies that a valid customer id is being used + * @ignore + * @param string $id customer id + * @throws InvalidArgumentException + */ + private function _validateCustomerId($id = null) + { + if (empty($id) || trim($id) == "") { + throw new InvalidArgumentException( + 'expected customer id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { + throw new InvalidArgumentException( + $id . ' is an invalid customer id.' + ); + } + + } + + /** + * determines if a string id or Customer object was passed + * @ignore + * @param mixed $customerOrId + * @return string customerId + */ + private function _determineCustomerId($customerOrId) + { + $customerId = ($customerOrId instanceof Customer) ? $customerOrId->id : $customerOrId; + $this->_validateCustomerId($customerId); + return $customerId; + + } + + /* private class methods */ + /** + * sends the create request to the gateway + * @ignore + * @param string $subPath + * @param array $params + * @return Result\Successful|Result\Error + */ + private function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new Address object and encapsulates + * it inside a Result\Successful object, or + * encapsulates an Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['address'])) { + // return a populated instance of Address + return new Result\Successful( + Address::factory($response['address']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected address or apiErrorResponse" + ); + } + + } +} +class_alias('Braintree\AddressGateway', 'Braintree_AddressGateway'); diff --git a/lib/Braintree/AmexExpressCheckoutCard.php b/lib/Braintree/AmexExpressCheckoutCard.php new file mode 100644 index 0000000..0185ec2 --- /dev/null +++ b/lib/Braintree/AmexExpressCheckoutCard.php @@ -0,0 +1,79 @@ +== More information == + * + * See {@link https://developers.braintreepayments.com/javascript+php}
+ * + * @package Braintree + * @category Resources + * + * @property-read string $createdAt + * @property-read string $default + * @property-read string $updatedAt + * @property-read string $customerId + * @property-read string $cardType + * @property-read string $bin + * @property-read string $cardMemberExpiryDate + * @property-read string $cardMemberNumber + * @property-read string $sourceDescription + * @property-read string $token + * @property-read string $imageUrl + * @property-read string $expirationMonth + * @property-read string $expirationYear + */ +class AmexExpressCheckoutCard extends Base +{ + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * factory method: returns an instance of AmexExpressCheckoutCard + * to the requesting method, with populated properties + * + * @ignore + * @return AmexExpressCheckoutCard + */ + public static function factory($attributes) + { + + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $amexExpressCheckoutCardAttribs array of Amex Express Checkout card properties + * @return void + */ + protected function _initialize($amexExpressCheckoutCardAttribs) + { + // set the attributes + $this->_attributes = $amexExpressCheckoutCardAttribs; + + $subscriptionArray = []; + if (isset($amexExpressCheckoutCardAttribs['subscriptions'])) { + foreach ($amexExpressCheckoutCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + } +} +class_alias('Braintree\AmexExpressCheckoutCard', 'Braintree_AmexExpressCheckoutCard'); diff --git a/lib/Braintree/AndroidPayCard.php b/lib/Braintree/AndroidPayCard.php new file mode 100644 index 0000000..50aae2d --- /dev/null +++ b/lib/Braintree/AndroidPayCard.php @@ -0,0 +1,89 @@ +== More information == + * + * See {@link https://developers.braintreepayments.com/javascript+php}
+ * + * @package Braintree + * @category Resources + * + * @property-read string $bin + * @property-read string $cardType + * @property-read string $createdAt + * @property-read string $customerId + * @property-read string $default + * @property-read string $expirationMonth + * @property-read string $expirationYear + * @property-read string $googleTransactionId + * @property-read string $imageUrl + * @property-read string $last4 + * @property-read string $sourceCardLast4 + * @property-read string $sourceCardType + * @property-read string $sourceDescription + * @property-read string $token + * @property-read string $updatedAt + * @property-read string $virtualCardLast4 + * @property-read string $virtualCardType + */ +class AndroidPayCard extends Base +{ + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * factory method: returns an instance of AndroidPayCard + * to the requesting method, with populated properties + * + * @ignore + * @return AndroidPayCard + */ + public static function factory($attributes) + { + $defaultAttributes = [ + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => $attributes['virtualCardLast4'], + 'cardType' => $attributes['virtualCardType'], + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $androidPayCardAttribs array of Android Pay card properties + * @return void + */ + protected function _initialize($androidPayCardAttribs) + { + // set the attributes + $this->_attributes = $androidPayCardAttribs; + + $subscriptionArray = []; + if (isset($androidPayCardAttribs['subscriptions'])) { + foreach ($androidPayCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + } +} +class_alias('Braintree\AndroidPayCard', 'Braintree_AndroidPayCard'); diff --git a/lib/Braintree/ApplePayCard.php b/lib/Braintree/ApplePayCard.php new file mode 100644 index 0000000..022bf7b --- /dev/null +++ b/lib/Braintree/ApplePayCard.php @@ -0,0 +1,100 @@ +== More information == + * + * See {@link https://developers.braintreepayments.com/javascript+php}
+ * + * @package Braintree + * @category Resources + * + * @property-read string $bin + * @property-read string $cardType + * @property-read string $createdAt + * @property-read string $customerId + * @property-read string $expirationDate + * @property-read string $expirationMonth + * @property-read string $expirationYear + * @property-read string $imageUrl + * @property-read string $last4 + * @property-read string $token + * @property-read string $paymentInstrumentName + * @property-read string $sourceDescription + * @property-read string $updatedAt + */ +class ApplePayCard extends Base +{ + // Card Type + const AMEX = 'Apple Pay - American Express'; + const MASTER_CARD = 'Apple Pay - MasterCard'; + const VISA = 'Apple Pay - Visa'; + + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * checks whether the card is expired based on the current date + * + * @return boolean + */ + public function isExpired() + { + return $this->expired; + } + + /** + * factory method: returns an instance of ApplePayCard + * to the requesting method, with populated properties + * + * @ignore + * @return ApplePayCard + */ + public static function factory($attributes) + { + $defaultAttributes = [ + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => '', + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $applePayCardAttribs array of Apple Pay card properties + * @return void + */ + protected function _initialize($applePayCardAttribs) + { + // set the attributes + $this->_attributes = $applePayCardAttribs; + + $subscriptionArray = []; + if (isset($applePayCardAttribs['subscriptions'])) { + foreach ($applePayCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); + } +} +class_alias('Braintree\ApplePayCard', 'Braintree_ApplePayCard'); diff --git a/lib/Braintree/ApplePayGateway.php b/lib/Braintree/ApplePayGateway.php new file mode 100644 index 0000000..c8291be --- /dev/null +++ b/lib/Braintree/ApplePayGateway.php @@ -0,0 +1,65 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function registerDomain($domain) + { + $path = $this->_config->merchantPath() . '/processing/apple_pay/validate_domains'; + $response = $this->_http->post($path, ['url' => $domain]); + if (array_key_exists('response', $response) && $response['response']['success']) + { + return new Result\Successful; + } + else if (array_key_exists('apiErrorResponse', $response)) + { + return new Result\Error($response['apiErrorResponse']); + } + } + + public function unregisterDomain($domain) + { + $path = $this->_config->merchantPath() . '/processing/apple_pay/unregister_domain'; + $this->_http->delete($path, ['url' => $domain]); + return new Result\Successful; + } + + public function registeredDomains() + { + $path = $this->_config->merchantPath() . '/processing/apple_pay/registered_domains'; + $response = $this->_http->get($path); + if (array_key_exists('response', $response) && array_key_exists('domains', $response['response'])) + { + $options = ApplePayOptions::factory($response['response']); + return new Result\Successful($options, 'applePayOptions'); + } + else if (array_key_exists('apiErrorResponse', $response)) + { + return new Result\Error($response['apiErrorResponse']); + } + else + { + throw new Exception\Unexpected('expected response or apiErrorResponse'); + } + } +} +class_alias('Braintree\ApplePayGateway', 'Braintree_ApplePayGateway'); diff --git a/lib/Braintree/ApplePayOptions.php b/lib/Braintree/ApplePayOptions.php new file mode 100644 index 0000000..40b2cef --- /dev/null +++ b/lib/Braintree/ApplePayOptions.php @@ -0,0 +1,28 @@ +_initialize($attributes); + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } +} +class_alias('Braintree\ApplePayOptions', 'Braintree_ApplePayOptions'); diff --git a/lib/Braintree/AuthorizationAdjustment.php b/lib/Braintree/AuthorizationAdjustment.php new file mode 100644 index 0000000..f8c14ba --- /dev/null +++ b/lib/Braintree/AuthorizationAdjustment.php @@ -0,0 +1,35 @@ +_initialize($attributes); + + return $instance; + } + + protected function _initialize($authorizationAdjustmentAttribs) + { + $this->_attributes = $authorizationAdjustmentAttribs; + } + + public function __toString() + { + return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; + } +} +class_alias('Braintree\AuthorizationAdjustment', 'Braintree_Authorization_Adjustment'); diff --git a/lib/Braintree/Base.php b/lib/Braintree/Base.php new file mode 100644 index 0000000..8e027c7 --- /dev/null +++ b/lib/Braintree/Base.php @@ -0,0 +1,88 @@ +_attributes)) { + return $this->_attributes[$name]; + } + else { + trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE); + return null; + } + } + + /** + * Checks for the existance of a property stored in the private $_attributes property + * + * @ignore + * @param string $name + * @return boolean + */ + public function __isset($name) + { + return array_key_exists($name, $this->_attributes); + } + + /** + * Mutator for instance properties stored in the private $_attributes property + * + * @ignore + * @param string $key + * @param mixed $value + */ + public function _set($key, $value) + { + $this->_attributes[$key] = $value; + } + + /** + * Implementation of JsonSerializable + * + * @ignore + * @return array + */ + public function jsonSerialize() + { + return $this->_attributes; + } +} diff --git a/lib/Braintree/BinData.php b/lib/Braintree/BinData.php new file mode 100644 index 0000000..cd971e9 --- /dev/null +++ b/lib/Braintree/BinData.php @@ -0,0 +1,30 @@ +_initialize($attributes); + + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } + + /** + * returns a string representation of the bin data + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + +} +class_alias('Braintree\BinData', 'Braintree_BinData'); diff --git a/lib/Braintree/ClientToken.php b/lib/Braintree/ClientToken.php new file mode 100644 index 0000000..f3d4884 --- /dev/null +++ b/lib/Braintree/ClientToken.php @@ -0,0 +1,49 @@ +clientToken()->generate($params); + } + + /** + * + * @param type $params + * @throws InvalidArgumentException + */ + public static function conditionallyVerifyKeys($params) + { + return Configuration::gateway()->clientToken()->conditionallyVerifyKeys($params); + } + + /** + * + * @return string client token retrieved from server + */ + public static function generateWithCustomerIdSignature() + { + return Configuration::gateway()->clientToken()->generateWithCustomerIdSignature(); + } + + /** + * + * @return string client token retrieved from server + */ + public static function generateWithoutCustomerIdSignature() + { + return Configuration::gateway()->clientToken()->generateWithoutCustomerIdSignature(); + } +} +class_alias('Braintree\ClientToken', 'Braintree_ClientToken'); diff --git a/lib/Braintree/ClientTokenGateway.php b/lib/Braintree/ClientTokenGateway.php new file mode 100644 index 0000000..b2fcbf5 --- /dev/null +++ b/lib/Braintree/ClientTokenGateway.php @@ -0,0 +1,129 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function generate($params=[]) + { + if (!array_key_exists("version", $params)) { + $params["version"] = ClientToken::DEFAULT_VERSION; + } + + $this->conditionallyVerifyKeys($params); + $generateParams = ["client_token" => $params]; + + return $this->_doGenerate('/client_token', $generateParams); + } + + /** + * sends the generate request to the gateway + * + * @ignore + * @param var $url + * @param array $params + * @return string + */ + public function _doGenerate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * + * @param array $params + * @throws InvalidArgumentException + */ + public function conditionallyVerifyKeys($params) + { + if (array_key_exists("customerId", $params)) { + Util::verifyKeys($this->generateWithCustomerIdSignature(), $params); + } else { + Util::verifyKeys($this->generateWithoutCustomerIdSignature(), $params); + } + } + + /** + * + * @return mixed[] + */ + public function generateWithCustomerIdSignature() + { + return [ + "version", "customerId", "proxyMerchantId", + ["options" => ["makeDefault", "verifyCard", "failOnDuplicatePaymentMethod"]], + "merchantAccountId"]; + } + + /** + * + * @return string[] + */ + public function generateWithoutCustomerIdSignature() + { + return ["version", "proxyMerchantId", "merchantAccountId"]; + } + + /** + * generic method for validating incoming gateway responses + * + * If the request is successful, returns a client token string. + * Otherwise, throws an InvalidArgumentException with the error + * response from the Gateway or an HTTP status code exception. + * + * @ignore + * @param array $response gateway response values + * @return string client token + * @throws InvalidArgumentException | HTTP status code exception + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['clientToken'])) { + return $response['clientToken']['value']; + } elseif (isset($response['apiErrorResponse'])) { + throw new InvalidArgumentException( + $response['apiErrorResponse']['message'] + ); + } else { + throw new Exception\Unexpected( + "Expected clientToken or apiErrorResponse" + ); + } + } + +} +class_alias('Braintree\ClientTokenGateway', 'Braintree_ClientTokenGateway'); diff --git a/lib/Braintree/CoinbaseAccount.php b/lib/Braintree/CoinbaseAccount.php new file mode 100644 index 0000000..a93fc1c --- /dev/null +++ b/lib/Braintree/CoinbaseAccount.php @@ -0,0 +1,110 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $customerId + * @property-read string $token + * @property-read string $userId + * @property-read string $userName + * @property-read string $userEmail + */ +class CoinbaseAccount extends Base +{ + /** + * factory method: returns an instance of CoinbaseAccount + * to the requesting method, with populated properties + * + * @ignore + * @return CoinbaseAccount + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $coinbaseAccountAttribs array of coinbaseAccount data + * @return void + */ + protected function _initialize($coinbaseAccountAttribs) + { + // set the attributes + $this->_attributes = $coinbaseAccountAttribs; + + $subscriptionArray = []; + if (isset($coinbaseAccountAttribs['subscriptions'])) { + foreach ($coinbaseAccountAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + + + // static methods redirecting to gateway + + public static function find($token) + { + return Configuration::gateway()->coinbaseAccount()->find($token); + } + + public static function update($token, $attributes) + { + return Configuration::gateway()->coinbaseAccount()->update($token, $attributes); + } + + public static function delete($token) + { + return Configuration::gateway()->coinbaseAccount()->delete($token); + } + + public static function sale($token, $transactionAttribs) + { + return Configuration::gateway()->coinbaseAccount()->sale($token, $transactionAttribs); + } +} +class_alias('Braintree\CoinbaseAccount', 'Braintree_CoinbaseAccount'); diff --git a/lib/Braintree/Collection.php b/lib/Braintree/Collection.php index 58293c3..1cbec1d 100644 --- a/lib/Braintree/Collection.php +++ b/lib/Braintree/Collection.php @@ -1,30 +1,31 @@ '', - 'merchantId' => '', - 'publicKey' => '', - 'privateKey' => '', - ); - /** - * - * @access protected - * @static - * @var array valid environments, used for validation - */ - private static $_validEnvironments = array( - 'development', - 'sandbox', - 'production', - 'qa', - ); + public function __construct($attribs = []) + { + foreach ($attribs as $kind => $value) { + if ($kind == 'environment') { + CredentialsParser::assertValidEnvironment($value); + $this->_environment = $value; + } + if ($kind == 'merchantId') { + $this->_merchantId = $value; + } + if ($kind == 'publicKey') { + $this->_publicKey = $value; + } + if ($kind == 'privateKey') { + $this->_privateKey = $value; + } + if ($kind == 'timeout') { + $this->_timeout = $value; + } + if ($kind == 'acceptGzipEncoding') { + $this->_acceptGzipEncoding = $value; + } + } + + if (isset($attribs['clientId']) || isset($attribs['accessToken'])) { + if (isset($attribs['environment']) || isset($attribs['merchantId']) || isset($attribs['publicKey']) || isset($attribs['privateKey'])) { + throw new Exception\Configuration('Cannot mix OAuth credentials (clientId, clientSecret, accessToken) with key credentials (publicKey, privateKey, environment, merchantId).'); + } + $parsedCredentials = new CredentialsParser($attribs); + + $this->_environment = $parsedCredentials->getEnvironment(); + $this->_merchantId = $parsedCredentials->getMerchantId(); + $this->_clientId = $parsedCredentials->getClientId(); + $this->_clientSecret = $parsedCredentials->getClientSecret(); + $this->_accessToken = $parsedCredentials->getAccessToken(); + } + } /** * resets configuration to default * @access public - * @static */ public static function reset() { - self::$_cache = array ( - 'environment' => '', - 'merchantId' => '', - 'publicKey' => '', - 'privateKey' => '', - ); + self::$global = new Configuration(); + } + + public static function gateway() + { + return new Gateway(self::$global); + } + + public static function environment($value=null) + { + if (empty($value)) { + return self::$global->getEnvironment(); + } + CredentialsParser::assertValidEnvironment($value); + self::$global->setEnvironment($value); + } + + public static function merchantId($value=null) + { + if (empty($value)) { + return self::$global->getMerchantId(); + } + self::$global->setMerchantId($value); + } + + public static function publicKey($value=null) + { + if (empty($value)) { + return self::$global->getPublicKey(); + } + self::$global->setPublicKey($value); + } + + public static function privateKey($value=null) + { + if (empty($value)) { + return self::$global->getPrivateKey(); + } + self::$global->setPrivateKey($value); } /** - * performs sanity checks when config settings are being set + * Sets or gets the read timeout to use for making requests. * - * @ignore - * @access protected - * @param string $key name of config setting - * @param string $value value to set - * @throws InvalidArgumentException - * @throws Braintree_Exception_Configuration - * @static - * @return boolean + * @param integer $value If provided, sets the read timeout + * @return integer The read timeout used for connecting to Braintree */ - private static function validate($key=null, $value=null) + public static function timeout($value=null) { - if (empty($key) && empty($value)) { - throw new InvalidArgumentException('nothing to validate'); + if (empty($value)) { + return self::$global->getTimeout(); } + self::$global->setTimeout($value); + } - if ($key === 'environment' && - !in_array($value, self::$_validEnvironments) ) { - throw new Braintree_Exception_Configuration('"' . - $value . '" is not a valid environment.'); + /** + * Sets or gets the SSL version to use for making requests. See + * https://php.net/manual/en/function.curl-setopt.php for possible + * CURLOPT_SSLVERSION values. + * + * @param integer $value If provided, sets the SSL version + * @return integer The SSL version used for connecting to Braintree + */ + public static function sslVersion($value=null) + { + if (empty($value)) { + return self::$global->getSslVersion(); } + self::$global->setSslVersion($value); + } - if (!isset(self::$_cache[$key])) { - throw new Braintree_Exception_Configuration($key . - ' is not a valid configuration setting.'); + /** + * Sets or gets the proxy host to use for connecting to Braintree + * + * @param string $value If provided, sets the proxy host + * @return string The proxy host used for connecting to Braintree + */ + public static function proxyHost($value = null) + { + if (empty($value)) { + return self::$global->getProxyHost(); } + self::$global->setProxyHost($value); + } + /** + * Sets or gets the port of the proxy to use for connecting to Braintree + * + * @param string $value If provided, sets the port of the proxy + * @return string The port of the proxy used for connecting to Braintree + */ + public static function proxyPort($value = null) + { if (empty($value)) { - throw new InvalidArgumentException($key . ' cannot be empty.'); + return self::$global->getProxyPort(); } + self::$global->setProxyPort($value); + } - return true; + /** + * Sets or gets the proxy type to use for connecting to Braintree. This value + * can be any of the CURLOPT_PROXYTYPE options in PHP cURL. + * + * @param string $value If provided, sets the proxy type + * @return string The proxy type used for connecting to Braintree + */ + public static function proxyType($value = null) + { + if (empty($value)) { + return self::$global->getProxyType(); + } + self::$global->setProxyType($value); } - private static function set($key, $value) + /** + * Specifies whether or not a proxy is properly configured + * + * @return bool true if a proxy is configured properly, false if not + */ + public static function isUsingProxy() { - // this method will raise an exception on invalid data - self::validate($key, $value); - // set the value in the cache - self::$_cache[$key] = $value; + $proxyHost = self::$global->getProxyHost(); + $proxyPort = self::$global->getProxyPort(); + return !empty($proxyHost) && !empty($proxyPort); + } + public static function proxyUser($value = null) + { + if (empty($value)) { + return self::$global->getProxyUser(); + } + self::$global->setProxyUser($value); } - private static function get($key) + public static function proxyPassword($value = null) { - // throw an exception if the value hasn't been set - if (isset(self::$_cache[$key]) && - (empty(self::$_cache[$key]))) { - throw new Braintree_Exception_Configuration( - $key.' needs to be set' - ); + if (empty($value)) { + return self::$global->getProxyPassword(); } + self::$global->setProxyPassword($value); + } + + /** + * Specified whether or not a username and password have been provided for + * use with an authenticated proxy + * + * @return bool true if both proxyUser and proxyPassword are present + */ + public static function isAuthenticatedProxy() + { + $proxyUser = self::$global->getProxyUser(); + $proxyPwd = self::$global->getProxyPassword(); + return !empty($proxyUser) && !empty($proxyPwd); + } - if (array_key_exists($key, self::$_cache)) { - return self::$_cache[$key]; + /** + * Specify if the HTTP client is able to decode gzipped responses. + * + * @param bool $value If true, will send an Accept-Encoding header with a gzip value. If false, will not send an Accept-Encoding header with a gzip value. + * @return bool true if an Accept-Encoding header with a gzip value will be sent, false if not + */ + public static function acceptGzipEncoding($value = null) + { + if (is_null($value)) { + return self::$global->getAcceptGzipEncoding(); } + self::$global->setAcceptGzipEncoding($value); + } - // return null by default to prevent __set from overloading - return null; + public static function assertGlobalHasAccessTokenOrKeys() + { + self::$global->assertHasAccessTokenOrKeys(); } + public function assertHasAccessTokenOrKeys() + { + if (empty($this->_accessToken)) { + if (empty($this->_merchantId)) { + throw new Exception\Configuration('Braintree\\Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree\\Gateway).'); + } else if (empty($this->_environment)) { + throw new Exception\Configuration('Braintree\\Configuration::environment needs to be set.'); + } else if (empty($this->_publicKey)) { + throw new Exception\Configuration('Braintree\\Configuration::publicKey needs to be set.'); + } else if (empty($this->_privateKey)) { + throw new Exception\Configuration('Braintree\\Configuration::privateKey needs to be set.'); + } + } + } - private static function setOrGet($name, $value = null) + public function assertHasClientCredentials() { - if (!empty($value) && is_array($value)) { - $value = $value[0]; + $this->assertHasClientId(); + $this->assertHasClientSecret(); + } + + public function assertHasClientId() + { + if (empty($this->_clientId)) { + throw new Exception\Configuration('clientId needs to be passed to Braintree\\Gateway.'); } - if (!empty($value)) { - self::set($name, $value); - } else { - return self::get($name); + } + + public function assertHasClientSecret() + { + if (empty($this->_clientSecret)) { + throw new Exception\Configuration('clientSecret needs to be passed to Braintree\\Gateway.'); } - return true; } - /**#@+ - * sets or returns the property after validation - * @access public - * @static - * @param string $value pass a string to set, empty to get - * @return mixed returns true on set + + public function getEnvironment() + { + return $this->_environment; + } + + /** + * Do not use this method directly. Pass in the environment to the constructor. */ - public static function environment($value = null) + public function setEnvironment($value) + { + $this->_environment = $value; + } + + public function getMerchantId() { - return self::setOrGet(__FUNCTION__, $value); + return $this->_merchantId; } - public static function merchantId($value = null) + /** + * Do not use this method directly. Pass in the merchantId to the constructor. + */ + public function setMerchantId($value) { - return self::setOrGet(__FUNCTION__, $value); + $this->_merchantId = $value; } - public static function publicKey($value = null) + public function getPublicKey() { - return self::setOrGet(__FUNCTION__, $value); + return $this->_publicKey; } - public static function privateKey($value = null) + public function getClientId() { - return self::setOrGet(__FUNCTION__, $value); + return $this->_clientId; } - /**#@-*/ /** - * returns the full merchant URL based on config values - * - * @access public - * @static - * @param none - * @return string merchant URL + * Do not use this method directly. Pass in the publicKey to the constructor. + */ + public function setPublicKey($value) + { + $this->_publicKey = $value; + } + + public function getPrivateKey() + { + return $this->_privateKey; + } + + public function getClientSecret() + { + return $this->_clientSecret; + } + + /** + * Do not use this method directly. Pass in the privateKey to the constructor. */ - public static function merchantUrl() + public function setPrivateKey($value) + { + $this->_privateKey = $value; + } + + private function setProxyHost($value) + { + $this->_proxyHost = $value; + } + + public function getProxyHost() + { + return $this->_proxyHost; + } + + private function setProxyPort($value) + { + $this->_proxyPort = $value; + } + + public function getProxyPort() + { + return $this->_proxyPort; + } + + private function setProxyType($value) + { + $this->_proxyType = $value; + } + + public function getProxyType() + { + return $this->_proxyType; + } + + private function setProxyUser($value) { - return self::baseUrl() . - self::merchantPath(); + $this->_proxyUser = $value; } + public function getProxyUser() + { + return $this->_proxyUser; + } + + private function setProxyPassword($value) + { + $this->_proxyPassword = $value; + } + + public function getProxyPassword() + { + return $this->_proxyPassword; + } + + private function setTimeout($value) + { + $this->_timeout = $value; + } + + public function getTimeout() + { + return $this->_timeout; + } + + private function setSslVersion($value) + { + $this->_sslVersion = $value; + } + + private function getSslVersion() + { + return $this->_sslVersion; + } + + public function getAcceptGzipEncoding() + { + return $this->_acceptGzipEncoding; + } + + private function setAcceptGzipEncoding($value) + { + $this->_acceptGzipEncoding = $value; + } + + public function getAccessToken() + { + return $this->_accessToken; + } + + public function isAccessToken() + { + return !empty($this->_accessToken); + } + + public function isClientCredentials() + { + return !empty($this->_clientId); + } /** * returns the base braintree gateway URL based on config values * * @access public - * @static * @param none * @return string braintree gateway URL */ - public static function baseUrl() + public function baseUrl() { - return self::protocol() . '://' . - self::serverName() . ':' . - self::portNumber(); + return sprintf('%s://%s:%d', $this->protocol(), $this->serverName(), $this->portNumber()); } + /** + * returns the base URL for Braintree's GraphQL endpoint based on config values + * + * @access public + * @param none + * @return string Braintree GraphQL URL + */ + public function graphQLBaseUrl() + { + return sprintf('%s://%s:%d/graphql', $this->protocol(), $this->graphQLServerName(), $this->graphQLPortNumber()); + } + /** * sets the merchant path based on merchant ID * * @access protected - * @static * @param none * @return string merchant path uri */ - public static function merchantPath() + public function merchantPath() { - return '/merchants/'.self::merchantId(); + return '/merchants/' . $this->_merchantId; } /** * sets the physical path for the location of the CA certs * * @access public - * @static * @param none * @return string filepath */ - public static function caFile($sslPath = NULL) + public function caFile($sslPath = NULL) { $sslPath = $sslPath ? $sslPath : DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'ssl' . DIRECTORY_SEPARATOR; - - $caPath = realpath( - dirname(__FILE__) . - $sslPath . 'api_braintreegateway_com.ca.crt' - ); + $caPath = __DIR__ . $sslPath . 'api_braintreegateway_com.ca.crt'; if (!file_exists($caPath)) { - throw new Braintree_Exception_SSLCaFileNotFound(); + throw new Exception\SSLCaFileNotFound(); } return $caPath; @@ -240,52 +506,65 @@ public static function caFile($sslPath = NULL) * returns the port number depending on environment * * @access public - * @static * @param none * @return int portnumber */ - public static function portNumber() + public function portNumber() { - if (self::sslOn()) { + if ($this->sslOn()) { return 443; } return getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000; } + /** + * returns the graphql port number depending on environment + * + * @access public + * @param none + * @return int graphql portnumber + */ + public function graphQLPortNumber() + { + if ($this->sslOn()) { + return 443; + } + return getenv("GRAPHQL_PORT") ?: 8080; + } + /** * returns http protocol depending on environment * * @access public - * @static * @param none * @return string http || https */ - public static function protocol() + public function protocol() { - return self::sslOn() ? 'https' : 'http'; + return $this->sslOn() ? 'https' : 'http'; } /** * returns gateway server name depending on environment * * @access public - * @static * @param none * @return string server domain name */ - public static function serverName() + public function serverName() { - switch(self::environment()) { + switch($this->_environment) { case 'production': $serverName = 'api.braintreegateway.com'; break; case 'qa': - $serverName = 'qa.braintreegateway.com'; + $serverName = 'gateway.qa.braintreepayments.com'; break; case 'sandbox': $serverName = 'api.sandbox.braintreegateway.com'; break; case 'development': + case 'integration': default: $serverName = 'localhost'; break; @@ -294,18 +573,69 @@ public static function serverName() return $serverName; } + /** + * returns Braintree GraphQL server name depending on environment + * + * @access public + * @param none + * @return string graphql domain name + */ + public function graphQLServerName() + { + switch($this->_environment) { + case 'production': + $graphQLServerName = 'payments.braintree-api.com'; + break; + case 'qa': + $graphQLServerName = 'payments-qa.dev.braintree-api.com'; + break; + case 'sandbox': + $graphQLServerName = 'payments.sandbox.braintree-api.com'; + break; + case 'development': + case 'integration': + default: + $graphQLServerName = 'graphql.bt.local'; + break; + } + + return $graphQLServerName; + } + + public function authUrl() + { + switch($this->_environment) { + case 'production': + $serverName = 'https://auth.venmo.com'; + break; + case 'qa': + $serverName = 'https://auth.qa.venmo.com'; + break; + case 'sandbox': + $serverName = 'https://auth.sandbox.venmo.com'; + break; + case 'development': + case 'integration': + default: + $serverName = 'http://auth.venmo.dev:9292'; + break; + } + + return $serverName; + } + /** * returns boolean indicating SSL is on or off for this session, * depending on environment * * @access public - * @static * @param none * @return boolean */ - public static function sslOn() + public function sslOn() { - switch(self::environment()) { + switch($this->_environment) { + case 'integration': case 'development': $ssl = false; break; @@ -326,9 +656,10 @@ public static function sslOn() * @param string $message * */ - public static function logMessage($message) + public function logMessage($message) { error_log('[Braintree] ' . $message); } - } +Configuration::reset(); +class_alias('Braintree\Configuration', 'Braintree_Configuration'); diff --git a/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php new file mode 100644 index 0000000..ca4e7ef --- /dev/null +++ b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php @@ -0,0 +1,37 @@ +_initialize($attributes); + $instance->_attributes['merchantId'] = $instance->_attributes['merchantPublicId']; + + return $instance; + } + + /** + * @ignore + */ + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } +} +class_alias('Braintree\ConnectedMerchantPayPalStatusChanged', 'Braintree_ConnectedMerchantPayPalStatusChanged'); diff --git a/lib/Braintree/ConnectedMerchantStatusTransitioned.php b/lib/Braintree/ConnectedMerchantStatusTransitioned.php new file mode 100644 index 0000000..4614437 --- /dev/null +++ b/lib/Braintree/ConnectedMerchantStatusTransitioned.php @@ -0,0 +1,37 @@ +_initialize($attributes); + $instance->_attributes['merchantId'] = $instance->_attributes['merchantPublicId']; + + return $instance; + } + + /** + * @ignore + */ + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } +} +class_alias('Braintree\ConnectedMerchantStatusTransitioned', 'Braintree_ConnectedMerchantStatusTransitioned'); diff --git a/lib/Braintree/CredentialsParser.php b/lib/Braintree/CredentialsParser.php new file mode 100644 index 0000000..034d973 --- /dev/null +++ b/lib/Braintree/CredentialsParser.php @@ -0,0 +1,147 @@ + $value) { + if ($kind == 'clientId') { + $this->_clientId = $value; + } + if ($kind == 'clientSecret') { + $this->_clientSecret = $value; + } + if ($kind == 'accessToken') { + $this->_accessToken = $value; + } + } + $this->parse(); + } + + /** + * + * @access protected + * @static + * @var array valid environments, used for validation + */ + private static $_validEnvironments = [ + 'development', + 'integration', + 'sandbox', + 'production', + 'qa', + ]; + + + public function parse() + { + $environments = []; + if (!empty($this->_clientId)) { + $environments[] = ['clientId', $this->_parseClientCredential('clientId', $this->_clientId, 'client_id')]; + } + if (!empty($this->_clientSecret)) { + $environments[] = ['clientSecret', $this->_parseClientCredential('clientSecret', $this->_clientSecret, 'client_secret')]; + } + if (!empty($this->_accessToken)) { + $environments[] = ['accessToken', $this->_parseAccessToken()]; + } + + $checkEnv = $environments[0]; + foreach ($environments as $env) { + if ($env[1] !== $checkEnv[1]) { + throw new Exception\Configuration( + 'Mismatched credential environments: ' . $checkEnv[0] . ' environment is ' . $checkEnv[1] . + ' and ' . $env[0] . ' environment is ' . $env[1]); + } + } + + self::assertValidEnvironment($checkEnv[1]); + $this->_environment = $checkEnv[1]; + } + + public static function assertValidEnvironment($environment) { + if (!in_array($environment, self::$_validEnvironments)) { + throw new Exception\Configuration('"' . + $environment . '" is not a valid environment.'); + } + } + + private function _parseClientCredential($credentialType, $value, $expectedValuePrefix) + { + $explodedCredential = explode('$', $value); + if (sizeof($explodedCredential) != 3) { + throw new Exception\Configuration('Incorrect ' . $credentialType . ' format. Expected: type$environment$token'); + } + + $gotValuePrefix = $explodedCredential[0]; + $environment = $explodedCredential[1]; + $token = $explodedCredential[2]; + + if ($gotValuePrefix != $expectedValuePrefix) { + throw new Exception\Configuration('Value passed for ' . $credentialType . ' is not a ' . $credentialType); + } + + return $environment; + } + + private function _parseAccessToken() + { + $accessTokenExploded = explode('$', $this->_accessToken); + if (sizeof($accessTokenExploded) != 4) { + throw new Exception\Configuration('Incorrect accessToken syntax. Expected: type$environment$merchant_id$token'); + } + + $gotValuePrefix = $accessTokenExploded[0]; + $environment = $accessTokenExploded[1]; + $merchantId = $accessTokenExploded[2]; + $token = $accessTokenExploded[3]; + + if ($gotValuePrefix != 'access_token') { + throw new Exception\Configuration('Value passed for accessToken is not an accessToken'); + } + + $this->_merchantId = $merchantId; + return $environment; + } + + public function getClientId() + { + return $this->_clientId; + } + + public function getClientSecret() + { + return $this->_clientSecret; + } + + public function getAccessToken() + { + return $this->_accessToken; + } + + public function getEnvironment() + { + return $this->_environment; + } + + public function getMerchantId() + { + return $this->_merchantId; + } +} +class_alias('Braintree\CredentialsParser', 'Braintree_CredentialsParser'); diff --git a/lib/Braintree/CreditCard.php b/lib/Braintree/CreditCard.php index 74ecff3..5b25e61 100644 --- a/lib/Braintree/CreditCard.php +++ b/lib/Braintree/CreditCard.php @@ -1,23 +1,17 @@ == More information == * - * For more detailed information on CreditCards, see {@link http://www.braintreepayments.com/gateway/credit-card-api http://www.braintreepaymentsolutions.com/gateway/credit-card-api}
- * For more detailed information on CreditCard verifications, see {@link http://www.braintreepayments.com/gateway/credit-card-verification-api http://www.braintreepaymentsolutions.com/gateway/credit-card-verification-api} + * For more detailed information on CreditCards, see {@link https://developers.braintreepayments.com/reference/response/credit-card/php https://developers.braintreepayments.com/reference/response/credit-card/php}
+ * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} * * @package Braintree * @category Resources - * @copyright 2010 Braintree Payment Solutions * * @property-read string $billingAddress * @property-read string $bin @@ -34,7 +28,7 @@ * @property-read string $token * @property-read string $updatedAt */ -class Braintree_CreditCard extends Braintree +class CreditCard extends Base { // Card Type const AMEX = 'American Express'; @@ -42,18 +36,20 @@ class Braintree_CreditCard extends Braintree const CHINA_UNION_PAY = 'China UnionPay'; const DINERS_CLUB_INTERNATIONAL = 'Diners Club'; const DISCOVER = 'Discover'; + const ELO = 'Elo'; const JCB = 'JCB'; const LASER = 'Laser'; const MAESTRO = 'Maestro'; + const UK_MAESTRO = 'UK Maestro'; const MASTER_CARD = 'MasterCard'; const SOLO = 'Solo'; const SWITCH_TYPE = 'Switch'; const VISA = 'Visa'; const UNKNOWN = 'Unknown'; - // Credit card origination location - const INTERNATIONAL = "international"; - const US = "us"; + // Credit card origination location + const INTERNATIONAL = "international"; + const US = "us"; const PREPAID_YES = 'Yes'; const PREPAID_NO = 'No'; @@ -81,523 +77,242 @@ class Braintree_CreditCard extends Braintree const COUNTRY_OF_ISSUANCE_UNKNOWN = "Unknown"; const ISSUING_BANK_UNKNOWN = "Unknown"; + const PRODUCT_ID_UNKNOWN = "Unknown"; - public static function create($attribs) - { - Braintree_Util::verifyKeys(self::createSignature(), $attribs); - return self::_doCreate('/payment_methods', array('credit_card' => $attribs)); - } - + /* instance methods */ /** - * attempts the create operation assuming all data will validate - * returns a Braintree_CreditCard object instead of a Result + * returns false if default is null or false * - * @access public - * @param array $attribs - * @return object - * @throws Braintree_Exception_ValidationError + * @return boolean */ - public static function createNoValidate($attribs) + public function isDefault() { - $result = self::create($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); + return $this->default; } + /** - * create a customer from a TransparentRedirect operation + * checks whether the card is expired based on the current date * - * @access public - * @param array $attribs - * @return object + * @return boolean */ - public static function createFromTransparentRedirect($queryString) + public function isExpired() { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return self::_doCreate( - '/payment_methods/all/confirm_transparent_redirect_request', - array('id' => $params['id']) - ); + return $this->expired; } /** + * checks whether the card is associated with venmo sdk * - * @access public - * @param none - * @return string + * @return boolean */ - public static function createCreditCardUrl() + public function isVenmoSdk() { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE); - return Braintree_Configuration::merchantUrl() . - '/payment_methods/all/create_via_transparent_redirect_request'; + return $this->venmoSdk; } /** - * returns a ResourceCollection of expired credit cards - * @return object ResourceCollection + * sets instance properties from an array of values + * + * @access protected + * @param array $creditCardAttribs array of creditcard data + * @return void */ - public static function expired() + protected function _initialize($creditCardAttribs) { - $response = Braintree_Http::post("/payment_methods/all/expired_ids"); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetchExpired', - 'methodArgs' => array() - ); - - return new Braintree_ResourceCollection($response, $pager); - } + // set the attributes + $this->_attributes = $creditCardAttribs; - public static function fetchExpired($ids) - { - $response = Braintree_Http::post("/payment_methods/all/expired", array('search' => array('ids' => $ids))); + // map each address into its own object + $billingAddress = isset($creditCardAttribs['billingAddress']) ? + Address::factory($creditCardAttribs['billingAddress']) : + null; - return Braintree_Util::extractattributeasarray( - $response['paymentMethods'], - 'creditCard' - ); - } - /** - * returns a ResourceCollection of credit cards expiring between start/end - * - * @return object ResourceCollection - */ - public static function expiringBetween($startDate, $endDate) - { - $queryPath = '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); - $response = Braintree_Http::post($queryPath); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetchExpiring', - 'methodArgs' => array($startDate, $endDate) - ); - - return new Braintree_ResourceCollection($response, $pager); - } + $subscriptionArray = []; + if (isset($creditCardAttribs['subscriptions'])) { + foreach ($creditCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } - public static function fetchExpiring($startDate, $endDate, $ids) - { - $queryPath = '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); - $response = Braintree_Http::post($queryPath, array('search' => array('ids' => $ids))); + $this->_set('subscriptions', $subscriptionArray); + $this->_set('billingAddress', $billingAddress); + $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); + $this->_set('maskedNumber', $this->bin . '******' . $this->last4); - return Braintree_Util::extractAttributeAsArray( - $response['paymentMethods'], - 'creditCard' - ); - } + if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { + $verifications = $creditCardAttribs['verifications']; + usort($verifications, [$this, '_compareCreatedAtOnVerifications']); - /** - * find a creditcard by token - * - * @access public - * @param string $token credit card unique id - * @return object Braintree_CreditCard - * @throws Braintree_Exception_NotFound - */ - public static function find($token) - { - self::_validateId($token); - try { - $response = Braintree_Http::get('/payment_methods/'.$token); - return self::factory($response['creditCard']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound( - 'credit card with token ' . $token . ' not found' - ); + $this->_set('verification', CreditCardVerification::factory($verifications[0])); } - } - /** - * create a credit on the card for the passed transaction - * - * @access public - * @param array $attribs - * @return object Braintree_Result_Successful or Braintree_Result_Error - */ - public static function credit($token, $transactionAttribs) + private function _compareCreatedAtOnVerifications($verificationAttrib1, $verificationAttrib2) { - self::_validateId($token); - return Braintree_Transaction::credit( - array_merge( - $transactionAttribs, - array('paymentMethodToken' => $token) - ) - ); + return ($verificationAttrib2['createdAt'] < $verificationAttrib1['createdAt']) ? -1 : 1; } /** - * create a credit on this card, assuming validations will pass + * returns false if comparing object is not a CreditCard, + * or is a CreditCard with a different id * - * returns a Braintree_Transaction object on success - * - * @access public - * @param array $attribs - * @return object Braintree_Transaction - * @throws Braintree_Exception_ValidationError + * @param object $otherCreditCard customer to compare against + * @return boolean */ - public static function creditNoValidate($token, $transactionAttribs) + public function isEqual($otherCreditCard) { - $result = self::credit($token, $transactionAttribs); - return self::returnObjectOrThrowException('Transaction', $result); + return !($otherCreditCard instanceof self) ? false : $this->token === $otherCreditCard->token; } /** - * create a new sale for the current card - * - * @param string $token - * @param array $transactionAttribs - * @return object Braintree_Result_Successful or Braintree_Result_Error - * @see Braintree_Transaction::sale() + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string */ - public static function sale($token, $transactionAttribs) + public function __toString() { - self::_validateId($token); - return Braintree_Transaction::sale( - array_merge( - $transactionAttribs, - array('paymentMethodToken' => $token) - ) - ); + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; } /** - * create a new sale using this card, assuming validations will pass - * - * returns a Braintree_Transaction object on success + * factory method: returns an instance of CreditCard + * to the requesting method, with populated properties * - * @access public - * @param array $transactionAttribs - * @param string $token - * @return object Braintree_Transaction - * @throws Braintree_Exception_ValidationsFailed - * @see Braintree_Transaction::sale() + * @ignore + * @return CreditCard */ - public static function saleNoValidate($token, $transactionAttribs) + public static function factory($attributes) { - $result = self::sale($token, $transactionAttribs); - return self::returnObjectOrThrowException('Transaction', $result); - } + $defaultAttributes = [ + 'bin' => '', + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => '', + ]; - /** - * updates the creditcard record - * - * if calling this method in static context, $token - * is the 2nd attribute. $token is not sent in object context. - * - * @access public - * @param array $attributes - * @param string $token (optional) - * @return object Braintree_Result_Successful or Braintree_Result_Error - */ - public static function update($token, $attributes) - { - Braintree_Util::verifyKeys(self::updateSignature(), $attributes); - self::_validateId($token); - return self::_doUpdate('put', '/payment_methods/' . $token, array('creditCard' => $attributes)); + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; } - /** - * update a creditcard record, assuming validations will pass - * - * if calling this method in static context, $token - * is the 2nd attribute. $token is not sent in object context. - * returns a Braintree_CreditCard object on success - * - * @access public - * @param array $attributes - * @param string $token - * @return object Braintree_CreditCard - * @throws Braintree_Exception_ValidationsFailed - */ - public static function updateNoValidate($token, $attributes) + + // static methods redirecting to gateway + + public static function create($attribs) { - $result = self::update($token, $attributes); - return self::returnObjectOrThrowException(__CLASS__, $result); + return Configuration::gateway()->creditCard()->create($attribs); } - /** - * - * @access public - * @param none - * @return string - */ - public static function updateCreditCardUrl() + + public static function createNoValidate($attribs) { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE); - return Braintree_Configuration::merchantUrl() . - '/payment_methods/all/update_via_transparent_redirect_request'; + return Configuration::gateway()->creditCard()->createNoValidate($attribs); } - /** - * update a customer from a TransparentRedirect operation - * - * @access public - * @param array $attribs - * @return object - */ - public static function updateFromTransparentRedirect($queryString) + public static function createFromTransparentRedirect($queryString) { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return self::_doUpdate( - 'post', - '/payment_methods/all/confirm_transparent_redirect_request', - array('id' => $params['id']) - ); + return Configuration::gateway()->creditCard()->createFromTransparentRedirect($queryString); } - /* instance methods */ - /** - * returns false if default is null or false - * - * @return boolean - */ - public function isDefault() + public static function createCreditCardUrl() { - return $this->default; + return Configuration::gateway()->creditCard()->createCreditCardUrl(); } - /** - * checks whether the card is expired based on the current date - * - * @return boolean - */ - public function isExpired() + public static function expired() { - return $this->expired; + return Configuration::gateway()->creditCard()->expired(); } - /** - * checks whether the card is associated with venmo sdk - * - * @return boolean - */ - public function isVenmoSdk() + public static function fetchExpired($ids) { - return $this->venmoSdk; + return Configuration::gateway()->creditCard()->fetchExpired($ids); } - public static function delete($token) + public static function expiringBetween($startDate, $endDate) { - self::_validateId($token); - Braintree_Http::delete('/payment_methods/' . $token); - return new Braintree_Result_Successful(); + return Configuration::gateway()->creditCard()->expiringBetween($startDate, $endDate); } - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $creditCardAttribs array of creditcard data - * @return none - */ - protected function _initialize($creditCardAttribs) + public static function fetchExpiring($startDate, $endDate, $ids) { - // set the attributes - $this->_attributes = $creditCardAttribs; - - // map each address into its own object - $billingAddress = isset($creditCardAttribs['billingAddress']) ? - Braintree_Address::factory($creditCardAttribs['billingAddress']) : - null; - - $subscriptionArray = array(); - if (isset($creditCardAttribs['subscriptions'])) { - foreach ($creditCardAttribs['subscriptions'] AS $subscription) { - $subscriptionArray[] = Braintree_Subscription::factory($subscription); - } - } - - $this->_set('subscriptions', $subscriptionArray); - $this->_set('billingAddress', $billingAddress); - $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); - $this->_set('maskedNumber', $this->bin . '******' . $this->last4); + return Configuration::gateway()->creditCard()->fetchExpiring($startDate, $endDate, $ids); } - /** - * returns false if comparing object is not a Braintree_CreditCard, - * or is a Braintree_CreditCard with a different id - * - * @param object $otherCreditCard customer to compare against - * @return boolean - */ - public function isEqual($otherCreditCard) + public static function find($token) { - return !($otherCreditCard instanceof Braintree_CreditCard) ? false : $this->token === $otherCreditCard->token; + return Configuration::gateway()->creditCard()->find($token); } - private static function baseOptions() + public static function fromNonce($nonce) { - return array('makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'venmoSdkSession'); + return Configuration::gateway()->creditCard()->fromNonce($nonce); } - private static function baseSignature($options) + public static function credit($token, $transactionAttribs) { - return array( - 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId', - 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode', - 'deviceData', 'fraudMerchantId', - array('options' => $options), - array( - 'billingAddress' => array( - 'firstName', - 'lastName', - 'company', - 'countryCodeAlpha2', - 'countryCodeAlpha3', - 'countryCodeNumeric', - 'countryName', - 'extendedAddress', - 'locality', - 'region', - 'postalCode', - 'streetAddress' - ), - ), - ); + return Configuration::gateway()->creditCard()->credit($token, $transactionAttribs); } - public static function createSignature() + public static function creditNoValidate($token, $transactionAttribs) { - $options = self::baseOptions(); - $options[] = "failOnDuplicatePaymentMethod"; - $signature = self::baseSignature($options); - $signature[] = 'customerId'; - return $signature; + return Configuration::gateway()->creditCard()->creditNoValidate($token, $transactionAttribs); } - public static function updateSignature() + public static function sale($token, $transactionAttribs) { - $signature = self::baseSignature(self::baseOptions()); - - $updateExistingBillingSignature = array( - array( - 'options' => array( - 'updateExisting' - ) - ) - ); - - foreach($signature AS $key => $value) { - if(is_array($value) and array_key_exists('billingAddress', $value)) { - $signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature); - } - } - - return $signature; + return Configuration::gateway()->creditCard()->sale($token, $transactionAttribs); } - /** - * sends the create request to the gateway - * - * @ignore - * @param string $url - * @param array $params - * @return mixed - */ - public static function _doCreate($url, $params) + public static function saleNoValidate($token, $transactionAttribs) { - $response = Braintree_Http::post($url, $params); - - return self::_verifyGatewayResponse($response); + return Configuration::gateway()->creditCard()->saleNoValidate($token, $transactionAttribs); } - /** - * create a printable representation of the object as: - * ClassName[property=value, property=value] - * @return string - */ - public function __toString() + public static function update($token, $attributes) { - return __CLASS__ . '[' . - Braintree_Util::attributesToString($this->_attributes) .']'; + return Configuration::gateway()->creditCard()->update($token, $attributes); } - /** - * verifies that a valid credit card token is being used - * @ignore - * @param string $token - * @throws InvalidArgumentException - */ - private static function _validateId($token = null) + public static function updateNoValidate($token, $attributes) { - if (empty($token)) { - throw new InvalidArgumentException( - 'expected credit card id to be set' - ); - } - if (!preg_match('/^[0-9A-Za-z_-]+$/', $token)) { - throw new InvalidArgumentException( - $token . ' is an invalid credit card id.' - ); - } + return Configuration::gateway()->creditCard()->updateNoValidate($token, $attributes); } - /** - * sends the update request to the gateway - * - * @ignore - * @param string $url - * @param array $params - * @return mixed - */ - private static function _doUpdate($httpVerb, $url, $params) + public static function updateCreditCardUrl() { - $response = Braintree_Http::$httpVerb($url, $params); - return self::_verifyGatewayResponse($response); + return Configuration::gateway()->creditCard()->updateCreditCardUrl(); } - /** - * generic method for validating incoming gateway responses - * - * creates a new Braintree_CreditCard object and encapsulates - * it inside a Braintree_Result_Successful object, or - * encapsulates a Braintree_Errors object inside a Result_Error - * alternatively, throws an Unexpected exception if the response is invalid. - * - * @ignore - * @param array $response gateway response values - * @return object Result_Successful or Result_Error - * @throws Braintree_Exception_Unexpected - */ - private static function _verifyGatewayResponse($response) + public static function updateFromTransparentRedirect($queryString) { - if (isset($response['creditCard'])) { - // return a populated instance of Braintree_Address - return new Braintree_Result_Successful( - self::factory($response['creditCard']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected address or apiErrorResponse" - ); - } + return Configuration::gateway()->creditCard()->updateFromTransparentRedirect($queryString); } - /** - * factory method: returns an instance of Braintree_CreditCard - * to the requesting method, with populated properties - * - * @ignore - * @return object instance of Braintree_CreditCard - */ - public static function factory($attributes) + public static function delete($token) { - $defaultAttributes = array( - 'bin' => '', - 'expirationMonth' => '', - 'expirationYear' => '', - 'last4' => '', - ); - - $instance = new self(); - $instance->_initialize(array_merge($defaultAttributes, $attributes)); - return $instance; + return Configuration::gateway()->creditCard()->delete($token); + } + + /** @return array */ + public static function allCardTypes() + { + return [ + CreditCard::AMEX, + CreditCard::CARTE_BLANCHE, + CreditCard::CHINA_UNION_PAY, + CreditCard::DINERS_CLUB_INTERNATIONAL, + CreditCard::DISCOVER, + CreditCard::ELO, + CreditCard::JCB, + CreditCard::LASER, + CreditCard::MAESTRO, + CreditCard::MASTER_CARD, + CreditCard::SOLO, + CreditCard::SWITCH_TYPE, + CreditCard::VISA, + CreditCard::UNKNOWN + ]; } } +class_alias('Braintree\CreditCard', 'Braintree_CreditCard'); diff --git a/lib/Braintree/CreditCardGateway.php b/lib/Braintree/CreditCardGateway.php new file mode 100644 index 0000000..5f8ce04 --- /dev/null +++ b/lib/Braintree/CreditCardGateway.php @@ -0,0 +1,486 @@ +== More information == + * + * For more detailed information on CreditCards, see {@link https://developers.braintreepayments.com/reference/response/credit-card/php https://developers.braintreepayments.com/reference/response/credit-card/php}
+ * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} + * + * @package Braintree + * @category Resources + */ +class CreditCardGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function create($attribs) + { + Util::verifyKeys(self::createSignature(), $attribs); + return $this->_doCreate('/payment_methods', ['credit_card' => $attribs]); + } + + /** + * attempts the create operation assuming all data will validate + * returns a CreditCard object instead of a Result + * + * @access public + * @param array $attribs + * @return CreditCard + * @throws Exception\ValidationError + */ + public function createNoValidate($attribs) + { + $result = $this->create($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + /** + * create a customer from a TransparentRedirect operation + * + * @deprecated since version 2.3.0 + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function createFromTransparentRedirect($queryString) + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + return $this->_doCreate( + '/payment_methods/all/confirm_transparent_redirect_request', + ['id' => $params['id']] + ); + } + + /** + * + * @deprecated since version 2.3.0 + * @access public + * @param none + * @return string + */ + public function createCreditCardUrl() + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); + return $this->_config->baseUrl() . $this->_config->merchantPath(). + '/payment_methods/all/create_via_transparent_redirect_request'; + } + + /** + * returns a ResourceCollection of expired credit cards + * @return ResourceCollection + */ + public function expired() + { + $path = $this->_config->merchantPath() . '/payment_methods/all/expired_ids'; + $response = $this->_http->post($path); + $pager = [ + 'object' => $this, + 'method' => 'fetchExpired', + 'methodArgs' => [] + ]; + + return new ResourceCollection($response, $pager); + } + + public function fetchExpired($ids) + { + $path = $this->_config->merchantPath() . "/payment_methods/all/expired"; + $response = $this->_http->post($path, ['search' => ['ids' => $ids]]); + + return Util::extractattributeasarray( + $response['paymentMethods'], + 'creditCard' + ); + } + /** + * returns a ResourceCollection of credit cards expiring between start/end + * + * @return ResourceCollection + */ + public function expiringBetween($startDate, $endDate) + { + $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); + $response = $this->_http->post($queryPath); + $pager = [ + 'object' => $this, + 'method' => 'fetchExpiring', + 'methodArgs' => [$startDate, $endDate] + ]; + + return new ResourceCollection($response, $pager); + } + + public function fetchExpiring($startDate, $endDate, $ids) + { + $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); + $response = $this->_http->post($queryPath, ['search' => ['ids' => $ids]]); + + return Util::extractAttributeAsArray( + $response['paymentMethods'], + 'creditCard' + ); + } + + /** + * find a creditcard by token + * + * @access public + * @param string $token credit card unique id + * @return CreditCard + * @throws Exception\NotFound + */ + public function find($token) + { + $this->_validateId($token); + try { + $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token; + $response = $this->_http->get($path); + return CreditCard::factory($response['creditCard']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'credit card with token ' . $token . ' not found' + ); + } + + } + + /** + * Convert a payment method nonce to a credit card + * + * @access public + * @param string $nonce payment method nonce + * @return CreditCard + * @throws Exception\NotFound + */ + public function fromNonce($nonce) + { + $this->_validateId($nonce, "nonce"); + try { + $path = $this->_config->merchantPath() . '/payment_methods/from_nonce/' . $nonce; + $response = $this->_http->get($path); + return CreditCard::factory($response['creditCard']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'credit card with nonce ' . $nonce . ' locked, consumed or not found' + ); + } + + } + + /** + * create a credit on the card for the passed transaction + * + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function credit($token, $transactionAttribs) + { + $this->_validateId($token); + return Transaction::credit( + array_merge( + $transactionAttribs, + ['paymentMethodToken' => $token] + ) + ); + } + + /** + * create a credit on this card, assuming validations will pass + * + * returns a Transaction object on success + * + * @access public + * @param array $attribs + * @return Transaction + * @throws Exception\ValidationError + */ + public function creditNoValidate($token, $transactionAttribs) + { + $result = $this->credit($token, $transactionAttribs); + return Util::returnObjectOrThrowException('Braintree\Transaction', $result); + } + + /** + * create a new sale for the current card + * + * @param string $token + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + * @see Transaction::sale() + */ + public function sale($token, $transactionAttribs) + { + $this->_validateId($token); + return Transaction::sale( + array_merge( + $transactionAttribs, + ['paymentMethodToken' => $token] + ) + ); + } + + /** + * create a new sale using this card, assuming validations will pass + * + * returns a Transaction object on success + * + * @access public + * @param array $transactionAttribs + * @param string $token + * @return Transaction + * @throws Exception\ValidationsFailed + * @see Transaction::sale() + */ + public function saleNoValidate($token, $transactionAttribs) + { + $result = $this->sale($token, $transactionAttribs); + return Util::returnObjectOrThrowException('Braintree\Transaction', $result); + } + + /** + * updates the creditcard record + * + * if calling this method in context, $token + * is the 2nd attribute. $token is not sent in object context. + * + * @access public + * @param array $attributes + * @param string $token (optional) + * @return Result\Successful|Result\Error + */ + public function update($token, $attributes) + { + Util::verifyKeys(self::updateSignature(), $attributes); + $this->_validateId($token); + return $this->_doUpdate('put', '/payment_methods/credit_card/' . $token, ['creditCard' => $attributes]); + } + + /** + * update a creditcard record, assuming validations will pass + * + * if calling this method in context, $token + * is the 2nd attribute. $token is not sent in object context. + * returns a CreditCard object on success + * + * @access public + * @param array $attributes + * @param string $token + * @return CreditCard + * @throws Exception\ValidationsFailed + */ + public function updateNoValidate($token, $attributes) + { + $result = $this->update($token, $attributes); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + /** + * + * @access public + * @param none + * @return string + */ + public function updateCreditCardUrl() + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); + return $this->_config->baseUrl() . $this->_config->merchantPath() . + '/payment_methods/all/update_via_transparent_redirect_request'; + } + + /** + * update a customer from a TransparentRedirect operation + * + * @deprecated since version 2.3.0 + * @access public + * @param array $attribs + * @return object + */ + public function updateFromTransparentRedirect($queryString) + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + return $this->_doUpdate( + 'post', + '/payment_methods/all/confirm_transparent_redirect_request', + ['id' => $params['id']] + ); + } + + public function delete($token) + { + $this->_validateId($token); + $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token; + $this->_http->delete($path); + return new Result\Successful(); + } + + private static function baseOptions() + { + return ['makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession']; + } + + private static function baseSignature($options) + { + return [ + 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId', + 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode', + 'deviceData', 'fraudMerchantId', 'paymentMethodNonce', + ['options' => $options], + [ + 'billingAddress' => self::billingAddressSignature() + ], + ]; + } + + public static function billingAddressSignature() + { + return [ + 'firstName', + 'lastName', + 'company', + 'countryCodeAlpha2', + 'countryCodeAlpha3', + 'countryCodeNumeric', + 'countryName', + 'extendedAddress', + 'locality', + 'region', + 'postalCode', + 'streetAddress' + ]; + } + + public static function createSignature() + { + $options = self::baseOptions(); + $options[] = "failOnDuplicatePaymentMethod"; + $signature = self::baseSignature($options); + $signature[] = 'customerId'; + return $signature; + } + + public static function updateSignature() + { + $options = self::baseOptions(); + $options[] = "failOnDuplicatePaymentMethod"; + $signature = self::baseSignature($options); + + $updateExistingBillingSignature = [ + [ + 'options' => [ + 'updateExisting' + ] + ] + ]; + + foreach($signature AS $key => $value) { + if(is_array($value) and array_key_exists('billingAddress', $value)) { + $signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature); + } + } + + return $signature; + } + + /** + * sends the create request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + public function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * verifies that a valid credit card identifier is being used + * @ignore + * @param string $identifier + * @param Optional $string $identifierType type of identifier supplied, default "token" + * @throws InvalidArgumentException + */ + private function _validateId($identifier = null, $identifierType = "token") + { + if (empty($identifier)) { + throw new InvalidArgumentException( + 'expected credit card id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { + throw new InvalidArgumentException( + $identifier . ' is an invalid credit card ' . $identifierType . '.' + ); + } + } + + /** + * sends the update request to the gateway + * + * @ignore + * @param string $url + * @param array $params + * @return mixed + */ + private function _doUpdate($httpVerb, $subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->$httpVerb($fullPath, $params); + return $this->_verifyGatewayResponse($response); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new CreditCard object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['creditCard'])) { + // return a populated instance of Address + return new Result\Successful( + CreditCard::factory($response['creditCard']) + ); + } elseif (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected address or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\CreditCardGateway', 'Braintree_CreditCardGateway'); diff --git a/lib/Braintree/CreditCardVerification.php b/lib/Braintree/CreditCardVerification.php index c20409d..ab9075c 100644 --- a/lib/Braintree/CreditCardVerification.php +++ b/lib/Braintree/CreditCardVerification.php @@ -1,5 +1,7 @@ name] = $term->toparam(); - } - $criteria["ids"] = Braintree_CreditCardVerificationSearch::ids()->in($ids)->toparam(); - $response = Braintree_Http::post('/verifications/advanced_search', array('search' => $criteria)); + Util::verifyKeys(self::createSignature(), $attributes); + return Configuration::gateway()->creditCardVerification()->create($attributes); + } - return Braintree_Util::extractattributeasarray( - $response['creditCardVerifications'], - 'verification' - ); + public static function fetch($query, $ids) + { + return Configuration::gateway()->creditCardVerification()->fetch($query, $ids); } public static function search($query) { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); - } - - $response = Braintree_Http::post('/verifications/advanced_search_ids', array('search' => $criteria)); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetch', - 'methodArgs' => array($query) - ); + return Configuration::gateway()->creditCardVerification()->search($query); + } - return new Braintree_ResourceCollection($response, $pager); + public static function createSignature() + { + return [ + ['options' => ['amount', 'merchantAccountId']], + ['creditCard' => + [ + 'cardholderName', 'cvv', 'number', + 'expirationDate', 'expirationMonth', 'expirationYear', + ['billingAddress' => CreditCardGateway::billingAddressSignature()] + ] + ]]; } } +class_alias('Braintree\CreditCardVerification', 'Braintree_CreditCardVerification'); diff --git a/lib/Braintree/CreditCardVerificationGateway.php b/lib/Braintree/CreditCardVerificationGateway.php new file mode 100644 index 0000000..869bd61 --- /dev/null +++ b/lib/Braintree/CreditCardVerificationGateway.php @@ -0,0 +1,74 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function create($attributes) + { + $response = $this->_http->post($this->_config->merchantPath() . "/verifications", ['verification' => $attributes]); + return $this->_verifyGatewayResponse($response); + } + + private function _verifyGatewayResponse($response) + { + + if(isset($response['verification'])){ + return new Result\Successful( + CreditCardVerification::factory($response['verification']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected transaction or apiErrorResponse" + ); + } + } + + public function fetch($query, $ids) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + $criteria["ids"] = CreditCardVerificationSearch::ids()->in($ids)->toparam(); + $path = $this->_config->merchantPath() . '/verifications/advanced_search'; + $response = $this->_http->post($path, ['search' => $criteria]); + + return Util::extractattributeasarray( + $response['creditCardVerifications'], + 'verification' + ); + } + + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + + $path = $this->_config->merchantPath() . '/verifications/advanced_search_ids'; + $response = $this->_http->post($path, ['search' => $criteria]); + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [$query] + ]; + + return new ResourceCollection($response, $pager); + } +} +class_alias('Braintree\CreditCardVerificationGateway', 'Braintree_CreditCardVerificationGateway'); diff --git a/lib/Braintree/CreditCardVerificationSearch.php b/lib/Braintree/CreditCardVerificationSearch.php index e799200..2dadff9 100644 --- a/lib/Braintree/CreditCardVerificationSearch.php +++ b/lib/Braintree/CreditCardVerificationSearch.php @@ -1,33 +1,56 @@ == More information == * - * For more detailed information on Customers, see {@link http://www.braintreepayments.com/gateway/customer-api http://www.braintreepaymentsolutions.com/gateway/customer-api} + * For more detailed information on Customers, see {@link https://developers.braintreepayments.com/reference/response/customer/php https://developers.braintreepayments.com/reference/response/customer/php} * * @package Braintree * @category Resources - * @copyright 2010 Braintree Payment Solutions * * @property-read array $addresses + * @property-read array $paymentMethods * @property-read string $company * @property-read string $createdAt * @property-read array $creditCards + * @property-read array $paypalAccounts + * @property-read array $applePayCards + * @property-read array $androidPayCards + * @property-read array $amexExpressCheckoutCards + * @property-read array $venmoAccounts + * @property-read array $visaCheckoutCards + * @property-read array $masterpassCards + * @property-read array $samsungPayCards + * @property-read array $coinbaseAccounts * @property-read array $customFields custom fields passed with the request * @property-read string $email * @property-read string $fax @@ -32,359 +36,188 @@ * @property-read string $updatedAt * @property-read string $website */ -class Braintree_Customer extends Braintree +class Customer extends Base { + /** + * + * @return Customer[] + */ public static function all() { - $response = Braintree_Http::post('/customers/advanced_search_ids'); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetch', - 'methodArgs' => array(array()) - ); - - return new Braintree_ResourceCollection($response, $pager); + return Configuration::gateway()->customer()->all(); } + /** + * + * @param string $query + * @param int[] $ids + * @return Customer|Customer[] + */ public static function fetch($query, $ids) { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); - } - $criteria["ids"] = Braintree_CustomerSearch::ids()->in($ids)->toparam(); - $response = Braintree_Http::post('/customers/advanced_search', array('search' => $criteria)); - - return Braintree_Util::extractattributeasarray( - $response['customers'], - 'customer' - ); + return Configuration::gateway()->customer()->fetch($query, $ids); } /** - * Creates a customer using the given +attributes+. If :id is not passed, - * the gateway will generate it. * - * - * $result = Braintree_Customer::create(array( - * 'first_name' => 'John', - * 'last_name' => 'Smith', - * 'company' => 'Smith Co.', - * 'email' => 'john@smith.com', - * 'website' => 'www.smithco.com', - * 'fax' => '419-555-1234', - * 'phone' => '614-555-1234' - * )); - * if($result->success) { - * echo 'Created customer ' . $result->customer->id; - * } else { - * echo 'Could not create customer, see result->errors'; - * } - * - * - * @access public * @param array $attribs - * @return object Result, either Successful or Error + * @return Result\Successful|Result\Error */ - public static function create($attribs = array()) + public static function create($attribs = []) { - Braintree_Util::verifyKeys(self::createSignature(), $attribs); - return self::_doCreate('/customers', array('customer' => $attribs)); + return Configuration::gateway()->customer()->create($attribs); } /** - * attempts the create operation assuming all data will validate - * returns a Braintree_Customer object instead of a Result * - * @access public * @param array $attribs - * @return object - * @throws Braintree_Exception_ValidationError + * @return Customer */ - public static function createNoValidate($attribs = array()) + public static function createNoValidate($attribs = []) { - $result = self::create($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); + return Configuration::gateway()->customer()->createNoValidate($attribs); } + /** - * create a customer from a TransparentRedirect operation - * - * @access public - * @param array $attribs - * @return object + * @deprecated since version 2.3.0 + * @param string $queryString + * @return Result\Successful */ public static function createFromTransparentRedirect($queryString) { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return self::_doCreate( - '/customers/all/confirm_transparent_redirect_request', - array('id' => $params['id']) - ); + return Configuration::gateway()->customer()->createFromTransparentRedirect($queryString); } /** - * - * @access public - * @param none + * @deprecated since version 2.3.0 * @return string */ public static function createCustomerUrl() { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE); - return Braintree_Configuration::merchantUrl() . - '/customers/all/create_via_transparent_redirect_request'; + return Configuration::gateway()->customer()->createCustomerUrl(); } - /** - * creates a full array signature of a valid create request - * @return array gateway create request format - */ - public static function createSignature() - { - - $creditCardSignature = Braintree_CreditCard::createSignature(); - unset($creditCardSignature['customerId']); - $signature = array( - 'id', 'company', 'email', 'fax', 'firstName', - 'lastName', 'phone', 'website', 'deviceData', - 'deviceSessionId', 'fraudMerchantId', - array('creditCard' => $creditCardSignature), - array('customFields' => array('_anyKey_')), - ); - return $signature; - } - - /** - * creates a full array signature of a valid update request - * @return array update request format - */ - public static function updateSignature() - { - $creditCardSignature = Braintree_CreditCard::updateSignature(); - - foreach($creditCardSignature AS $key => $value) { - if(is_array($value) and array_key_exists('options', $value)) { - array_push($creditCardSignature[$key]['options'], 'updateExistingToken'); - } - } - - $signature = array( - 'id', 'company', 'email', 'fax', 'firstName', - 'lastName', 'phone', 'website', 'deviceData', - 'deviceSessionId', 'fraudMerchantId', - array('creditCard' => $creditCardSignature), - array('customFields' => array('_anyKey_')), - ); - return $signature; - } - - - /** - * find a customer by id * - * @access public - * @param string id customer Id - * @return object Braintree_Customer - * @throws Braintree_Exception_NotFound + * @throws Exception\NotFound + * @param string $id customer id + * @return Customer */ - public static function find($id) + public static function find($id, $associationFilterId = null) { - self::_validateId($id); - try { - $response = Braintree_Http::get('/customers/'.$id); - return self::factory($response['customer']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound( - 'customer with id ' . $id . ' not found' - ); - } - + return Configuration::gateway()->customer()->find($id, $associationFilterId); } /** - * credit a customer for the passed transaction * - * @access public - * @param array $attribs - * @return object Braintree_Result_Successful or Braintree_Result_Error + * @param int $customerId + * @param array $transactionAttribs + * @return Result\Successful|Result\Error */ public static function credit($customerId, $transactionAttribs) { - self::_validateId($customerId); - return Braintree_Transaction::credit( - array_merge($transactionAttribs, - array('customerId' => $customerId) - ) - ); + return Configuration::gateway()->customer()->credit($customerId, $transactionAttribs); } /** - * credit a customer, assuming validations will pass * - * returns a Braintree_Transaction object on success - * - * @access public - * @param array $attribs - * @return object Braintree_Transaction - * @throws Braintree_Exception_ValidationError + * @throws Exception\ValidationError + * @param type $customerId + * @param type $transactionAttribs + * @return Transaction */ public static function creditNoValidate($customerId, $transactionAttribs) { - $result = self::credit($customerId, $transactionAttribs); - return self::returnObjectOrThrowException('Braintree_Transaction', $result); + return Configuration::gateway()->customer()->creditNoValidate($customerId, $transactionAttribs); } /** - * delete a customer by id * - * @param string $customerId + * @throws Exception on invalid id or non-200 http response code + * @param int $customerId + * @return Result\Successful */ public static function delete($customerId) { - self::_validateId($customerId); - Braintree_Http::delete('/customers/' . $customerId); - return new Braintree_Result_Successful(); + return Configuration::gateway()->customer()->delete($customerId); } /** - * create a new sale for a customer * - * @param string $customerId + * @param int $customerId * @param array $transactionAttribs - * @return object Braintree_Result_Successful or Braintree_Result_Error - * @see Braintree_Transaction::sale() + * @return Transaction */ public static function sale($customerId, $transactionAttribs) { - self::_validateId($customerId); - return Braintree_Transaction::sale( - array_merge($transactionAttribs, - array('customerId' => $customerId) - ) - ); + return Configuration::gateway()->customer()->sale($customerId, $transactionAttribs); } /** - * create a new sale for a customer, assuming validations will pass * - * returns a Braintree_Transaction object on success - * @access public - * @param string $customerId + * @param int $customerId * @param array $transactionAttribs - * @return object Braintree_Transaction - * @throws Braintree_Exception_ValidationsFailed - * @see Braintree_Transaction::sale() + * @return Transaction */ public static function saleNoValidate($customerId, $transactionAttribs) { - $result = self::sale($customerId, $transactionAttribs); - return self::returnObjectOrThrowException('Braintree_Transaction', $result); + return Configuration::gateway()->customer()->saleNoValidate($customerId, $transactionAttribs); } /** - * Returns a ResourceCollection of customers matching the search query. * - * If query is a string, the search will be a basic search. - * If query is a hash, the search will be an advanced search. - * For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/customer-api#searching http://www.braintreepaymentsolutions.com/gateway/customer-api} - * - * @param mixed $query search query - * @param array $options options such as page number - * @return object Braintree_ResourceCollection * @throws InvalidArgumentException + * @param string $query + * @return ResourceCollection */ public static function search($query) { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); - } - - $response = Braintree_Http::post('/customers/advanced_search_ids', array('search' => $criteria)); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetch', - 'methodArgs' => array($query) - ); - - return new Braintree_ResourceCollection($response, $pager); + return Configuration::gateway()->customer()->search($query); } /** - * updates the customer record * - * if calling this method in static context, customerId - * is the 2nd attribute. customerId is not sent in object context. - * - * @access public + * @throws Exception\Unexpected + * @param int $customerId * @param array $attributes - * @param string $customerId (optional) - * @return object Braintree_Result_Successful or Braintree_Result_Error + * @return Result\Successful|Result\Error */ public static function update($customerId, $attributes) { - Braintree_Util::verifyKeys(self::updateSignature(), $attributes); - self::_validateId($customerId); - return self::_doUpdate( - 'put', - '/customers/' . $customerId, - array('customer' => $attributes) - ); + return Configuration::gateway()->customer()->update($customerId, $attributes); } /** - * update a customer record, assuming validations will pass - * - * if calling this method in static context, customerId - * is the 2nd attribute. customerId is not sent in object context. - * returns a Braintree_Customer object on success * - * @access public + * @throws Exception\Unexpected + * @param int $customerId * @param array $attributes - * @param string $customerId - * @return object Braintree_Customer - * @throws Braintree_Exception_ValidationsFailed + * @return CustomerGateway */ public static function updateNoValidate($customerId, $attributes) { - $result = self::update($customerId, $attributes); - return self::returnObjectOrThrowException(__CLASS__, $result); + return Configuration::gateway()->customer()->updateNoValidate($customerId, $attributes); } + /** * - * @access public - * @param none + * @deprecated since version 2.3.0 * @return string */ public static function updateCustomerUrl() { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE); - return Braintree_Configuration::merchantUrl() . - '/customers/all/update_via_transparent_redirect_request'; + return Configuration::gateway()->customer()->updateCustomerUrl(); } /** - * update a customer from a TransparentRedirect operation * - * @access public - * @param array $attribs - * @return object + * @deprecated since version 2.3.0 + * @param string $queryString + * @return Result\Successful|Result\Error */ public static function updateFromTransparentRedirect($queryString) { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return self::_doUpdate( - 'post', - '/customers/all/confirm_transparent_redirect_request', - array('id' => $params['id']) - ); + return Configuration::gateway()->customer()->updateFromTransparentRedirect($queryString); } /* instance methods */ @@ -395,32 +228,121 @@ public static function updateFromTransparentRedirect($queryString) * @ignore * @access protected * @param array $customerAttribs array of customer data - * @return none */ protected function _initialize($customerAttribs) { - // set the attributes $this->_attributes = $customerAttribs; - // map each address into its own object - $addressArray = array(); + $addressArray = []; if (isset($customerAttribs['addresses'])) { foreach ($customerAttribs['addresses'] AS $address) { - $addressArray[] = Braintree_Address::factory($address); + $addressArray[] = Address::factory($address); } } $this->_set('addresses', $addressArray); - // map each creditcard into its own object - $ccArray = array(); + $creditCardArray = []; if (isset($customerAttribs['creditCards'])) { foreach ($customerAttribs['creditCards'] AS $creditCard) { - $ccArray[] = Braintree_CreditCard::factory($creditCard); + $creditCardArray[] = CreditCard::factory($creditCard); } } - $this->_set('creditCards', $ccArray); + $this->_set('creditCards', $creditCardArray); + $coinbaseAccountArray = []; + if (isset($customerAttribs['coinbaseAccounts'])) { + foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) { + $coinbaseAccountArray[] = CoinbaseAccount::factory($coinbaseAccount); + } + } + $this->_set('coinbaseAccounts', $coinbaseAccountArray); + + $paypalAccountArray = []; + if (isset($customerAttribs['paypalAccounts'])) { + foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { + $paypalAccountArray[] = PayPalAccount::factory($paypalAccount); + } + } + $this->_set('paypalAccounts', $paypalAccountArray); + + $applePayCardArray = []; + if (isset($customerAttribs['applePayCards'])) { + foreach ($customerAttribs['applePayCards'] AS $applePayCard) { + $applePayCardArray[] = ApplePayCard::factory($applePayCard); + } + } + $this->_set('applePayCards', $applePayCardArray); + + $androidPayCardArray = []; + if (isset($customerAttribs['androidPayCards'])) { + foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) { + $androidPayCardArray[] = AndroidPayCard::factory($androidPayCard); + } + } + $this->_set('androidPayCards', $androidPayCardArray); + + $amexExpressCheckoutCardArray = []; + if (isset($customerAttribs['amexExpressCheckoutCards'])) { + foreach ($customerAttribs['amexExpressCheckoutCards'] AS $amexExpressCheckoutCard) { + $amexExpressCheckoutCardArray[] = AmexExpressCheckoutCard::factory($amexExpressCheckoutCard); + } + } + $this->_set('amexExpressCheckoutCards', $amexExpressCheckoutCardArray); + + $venmoAccountArray = array(); + if (isset($customerAttribs['venmoAccounts'])) { + foreach ($customerAttribs['venmoAccounts'] AS $venmoAccount) { + $venmoAccountArray[] = VenmoAccount::factory($venmoAccount); + } + } + $this->_set('venmoAccounts', $venmoAccountArray); + + $visaCheckoutCardArray = []; + if (isset($customerAttribs['visaCheckoutCards'])) { + foreach ($customerAttribs['visaCheckoutCards'] AS $visaCheckoutCard) { + $visaCheckoutCardArray[] = VisaCheckoutCard::factory($visaCheckoutCard); + } + } + $this->_set('visaCheckoutCards', $visaCheckoutCardArray); + + $masterpassCardArray = []; + if (isset($customerAttribs['masterpassCards'])) { + foreach ($customerAttribs['masterpassCards'] AS $masterpassCard) { + $masterpassCardArray[] = MasterpassCard::factory($masterpassCard); + } + } + $this->_set('masterpassCards', $masterpassCardArray); + + $samsungPayCardArray = []; + if (isset($customerAttribs['samsungPayCards'])) { + foreach ($customerAttribs['samsungPayCards'] AS $samsungPayCard) { + $samsungPayCardArray[] = SamsungPayCard::factory($samsungPayCard); + } + } + $this->_set('samsungPayCards', $samsungPayCardArray); + + $usBankAccountArray = array(); + if (isset($customerAttribs['usBankAccounts'])) { + foreach ($customerAttribs['usBankAccounts'] AS $usBankAccount) { + $usBankAccountArray[] = UsBankAccount::factory($usBankAccount); + } + } + $this->_set('usBankAccounts', $usBankAccountArray); + + $this->_set('paymentMethods', array_merge( + $this->creditCards, + $this->paypalAccounts, + $this->applePayCards, + $this->coinbaseAccounts, + $this->androidPayCards, + $this->amexExpressCheckoutCards, + $this->venmoAccounts, + $this->visaCheckoutCards, + $this->masterpassCards, + $this->samsungPayCards, + $this->usBankAccounts + )); } /** @@ -430,19 +352,47 @@ protected function _initialize($customerAttribs) public function __toString() { return __CLASS__ . '[' . - Braintree_Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) .']'; } /** - * returns false if comparing object is not a Braintree_Customer, - * or is a Braintree_Customer with a different id + * returns false if comparing object is not a Customer, + * or is a Customer with a different id * * @param object $otherCust customer to compare against * @return boolean */ public function isEqual($otherCust) { - return !($otherCust instanceof Braintree_Customer) ? false : $this->id === $otherCust->id; + return !($otherCust instanceof Customer) ? false : $this->id === $otherCust->id; + } + + /** + * returns an array containt all of the customer's payment methods + * + * @deprecated since version 3.1.0 - use the paymentMethods property directly + * + * @return array + */ + public function paymentMethods() + { + return $this->paymentMethods; + } + + /** + * returns the customer's default payment method + * + * @return CreditCard|PayPalAccount + */ + public function defaultPaymentMethod() + { + $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree\Customer::_defaultPaymentMethodFilter'); + return current($defaultPaymentMethods); + } + + public static function _defaultPaymentMethodFilter($paymentMethod) + { + return $paymentMethod->isDefault(); } /* private class properties */ @@ -451,7 +401,7 @@ public function isEqual($otherCust) * @access protected * @var array registry of customer data */ - protected $_attributes = array( + protected $_attributes = [ 'addresses' => '', 'company' => '', 'creditCards' => '', @@ -464,101 +414,21 @@ public function isEqual($otherCust) 'createdAt' => '', 'updatedAt' => '', 'website' => '', - ); - - /** - * sends the create request to the gateway - * - * @ignore - * @param string $url - * @param array $params - * @return mixed - */ - public static function _doCreate($url, $params) - { - $response = Braintree_Http::post($url, $params); - - return self::_verifyGatewayResponse($response); - } + ]; /** - * verifies that a valid customer id is being used - * @ignore - * @param string customer id - * @throws InvalidArgumentException - */ - private static function _validateId($id = null) { - if (empty($id)) { - throw new InvalidArgumentException( - 'expected customer id to be set' - ); - } - if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid customer id.' - ); - } - } - - - /* private class methods */ - - /** - * sends the update request to the gateway - * - * @ignore - * @param string $url - * @param array $params - * @return mixed - */ - private static function _doUpdate($httpVerb, $url, $params) - { - $response = Braintree_Http::$httpVerb($url, $params); - - return self::_verifyGatewayResponse($response); - } - - /** - * generic method for validating incoming gateway responses - * - * creates a new Braintree_Customer object and encapsulates - * it inside a Braintree_Result_Successful object, or - * encapsulates a Braintree_Errors object inside a Result_Error - * alternatively, throws an Unexpected exception if the response is invalid. - * - * @ignore - * @param array $response gateway response values - * @return object Result_Successful or Result_Error - * @throws Braintree_Exception_Unexpected - */ - private static function _verifyGatewayResponse($response) - { - if (isset($response['customer'])) { - // return a populated instance of Braintree_Customer - return new Braintree_Result_Successful( - self::factory($response['customer']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected customer or apiErrorResponse" - ); - } - } - - /** - * factory method: returns an instance of Braintree_Customer + * factory method: returns an instance of Customer * to the requesting method, with populated properties * * @ignore - * @return object instance of Braintree_Customer + * @param array $attributes + * @return Customer */ public static function factory($attributes) { - $instance = new self(); + $instance = new Customer(); $instance->_initialize($attributes); return $instance; } - } +class_alias('Braintree\Customer', 'Braintree_Customer'); diff --git a/lib/Braintree/CustomerGateway.php b/lib/Braintree/CustomerGateway.php new file mode 100644 index 0000000..3834509 --- /dev/null +++ b/lib/Braintree/CustomerGateway.php @@ -0,0 +1,662 @@ +== More information == + * + * For more detailed information on Customers, see {@link https://developers.braintreepayments.com/reference/response/customer/php https://developers.braintreepayments.com/reference/response/customer/php} + * + * @package Braintree + * @category Resources + */ +class CustomerGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function all() + { + $path = $this->_config->merchantPath() . '/customers/advanced_search_ids'; + $response = $this->_http->post($path); + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [[]] + ]; + + return new ResourceCollection($response, $pager); + } + + public function fetch($query, $ids) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + $criteria["ids"] = CustomerSearch::ids()->in($ids)->toparam(); + $path = $this->_config->merchantPath() . '/customers/advanced_search'; + $response = $this->_http->post($path, ['search' => $criteria]); + + return Util::extractattributeasarray( + $response['customers'], + 'customer' + ); + } + + /** + * Creates a customer using the given +attributes+. If :id is not passed, + * the gateway will generate it. + * + * + * $result = Customer::create(array( + * 'first_name' => 'John', + * 'last_name' => 'Smith', + * 'company' => 'Smith Co.', + * 'email' => 'john@smith.com', + * 'website' => 'www.smithco.com', + * 'fax' => '419-555-1234', + * 'phone' => '614-555-1234' + * )); + * if($result->success) { + * echo 'Created customer ' . $result->customer->id; + * } else { + * echo 'Could not create customer, see result->errors'; + * } + * + * + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function create($attribs = []) + { + Util::verifyKeys(self::createSignature(), $attribs); + return $this->_doCreate('/customers', ['customer' => $attribs]); + } + + /** + * attempts the create operation assuming all data will validate + * returns a Customer object instead of a Result + * + * @access public + * @param array $attribs + * @return Customer + * @throws Exception\ValidationError + */ + public function createNoValidate($attribs = []) + { + $result = $this->create($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + /** + * create a customer from a TransparentRedirect operation + * + * @deprecated since version 2.3.0 + * @access public + * @param array $attribs + * @return Customer + */ + public function createFromTransparentRedirect($queryString) + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + return $this->_doCreate( + '/customers/all/confirm_transparent_redirect_request', + ['id' => $params['id']] + ); + } + + /** + * + * @deprecated since version 2.3.0 + * @access public + * @param none + * @return string + */ + public function createCustomerUrl() + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); + return $this->_config->baseUrl() . $this->_config->merchantPath() . + '/customers/all/create_via_transparent_redirect_request'; + } + + + /** + * creates a full array signature of a valid create request + * @return array gateway create request format + */ + public static function createSignature() + { + $creditCardSignature = CreditCardGateway::createSignature(); + unset($creditCardSignature[array_search('customerId', $creditCardSignature)]); + + $signature = [ + 'id', 'company', 'email', 'fax', 'firstName', + 'lastName', 'phone', 'website', 'deviceData', + 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce', + ['riskData' => + ['customerBrowser', 'customerIp', 'customer_browser', 'customer_ip'] + ], + ['creditCard' => $creditCardSignature], + ['customFields' => ['_anyKey_']], + ['options' => [ + ['paypal' => [ + 'payee_email', + 'payeeEmail', + 'order_id', + 'orderId', + 'custom_field', + 'customField', + 'description', + 'amount', + ['shipping' => + [ + 'firstName', 'lastName', 'company', 'countryName', + 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'extendedAddress', 'locality', 'postalCode', 'region', + 'streetAddress'], + ], + ]] + ]], + ]; + return $signature; + } + + /** + * creates a full array signature of a valid update request + * @return array update request format + */ + public static function updateSignature() + { + $creditCardSignature = CreditCardGateway::updateSignature(); + + foreach($creditCardSignature AS $key => $value) { + if(is_array($value) and array_key_exists('options', $value)) { + array_push($creditCardSignature[$key]['options'], 'updateExistingToken'); + } + } + + $signature = [ + 'id', 'company', 'email', 'fax', 'firstName', + 'lastName', 'phone', 'website', 'deviceData', + 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce', 'defaultPaymentMethodToken', + ['creditCard' => $creditCardSignature], + ['customFields' => ['_anyKey_']], + ['options' => [ + ['paypal' => [ + 'payee_email', + 'payeeEmail', + ['shipping' => + [ + 'firstName', 'lastName', 'company', 'countryName', + 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'extendedAddress', 'locality', 'postalCode', 'region', + 'streetAddress'], + ], + ]], + ]], + ]; + return $signature; + } + + + /** + * find a customer by id + * + * @access public + * @param string id customer Id + * @param string associationFilterId association filter Id + * @return Customer|boolean The customer object or false if the request fails. + * @throws Exception\NotFound + */ + public function find($id, $associationFilterId = null) + { + $this->_validateId($id); + try { + $queryParams = ''; + if ($associationFilterId) { + $queryParams = '?association_filter_id=' . $associationFilterId; + } + $path = $this->_config->merchantPath() . '/customers/' . $id . $queryParams; + $response = $this->_http->get($path); + return Customer::factory($response['customer']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'customer with id ' . $id . ' not found' + ); + } + } + + /** + * credit a customer for the passed transaction + * + * @access public + * @param int $customerId + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + */ + public function credit($customerId, $transactionAttribs) + { + $this->_validateId($customerId); + return Transaction::credit( + array_merge($transactionAttribs, + ['customerId' => $customerId] + ) + ); + } + + /** + * credit a customer, assuming validations will pass + * + * returns a Transaction object on success + * + * @access public + * @param int $customerId + * @param array $transactionAttribs + * @return Transaction + * @throws Exception\ValidationError + */ + public function creditNoValidate($customerId, $transactionAttribs) + { + $result = $this->credit($customerId, $transactionAttribs); + return Util::returnObjectOrThrowException('Braintree\Transaction', $result); + } + + /** + * delete a customer by id + * + * @param string $customerId + */ + public function delete($customerId) + { + $this->_validateId($customerId); + $path = $this->_config->merchantPath() . '/customers/' . $customerId; + $this->_http->delete($path); + return new Result\Successful(); + } + + /** + * create a new sale for a customer + * + * @param string $customerId + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + * @see Transaction::sale() + */ + public function sale($customerId, $transactionAttribs) + { + $this->_validateId($customerId); + return Transaction::sale( + array_merge($transactionAttribs, + ['customerId' => $customerId] + ) + ); + } + + /** + * create a new sale for a customer, assuming validations will pass + * + * returns a Transaction object on success + * @access public + * @param string $customerId + * @param array $transactionAttribs + * @return Transaction + * @throws Exception\ValidationsFailed + * @see Transaction::sale() + */ + public function saleNoValidate($customerId, $transactionAttribs) + { + $result = $this->sale($customerId, $transactionAttribs); + return Util::returnObjectOrThrowException('Braintree\Transaction', $result); + } + + /** + * Returns a ResourceCollection of customers matching the search query. + * + * If query is a string, the search will be a basic search. + * If query is a hash, the search will be an advanced search. + * For more detailed information and examples, see {@link https://developers.braintreepayments.com/reference/request/customer/search/php https://developers.braintreepayments.com/reference/request/customer/search/php} + * + * @param mixed $query search query + * @return ResourceCollection + * @throws InvalidArgumentException + */ + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $result = $term->toparam(); + if(is_null($result) || empty($result)) { + throw new InvalidArgumentException('Operator must be provided'); + } + + $criteria[$term->name] = $term->toparam(); + } + + $path = $this->_config->merchantPath() . '/customers/advanced_search_ids'; + $response = $this->_http->post($path, ['search' => $criteria]); + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [$query] + ]; + + return new ResourceCollection($response, $pager); + } + + /** + * updates the customer record + * + * if calling this method in static context, customerId + * is the 2nd attribute. customerId is not sent in object context. + * + * @access public + * @param string $customerId (optional) + * @param array $attributes + * @return Result\Successful|Result\Error + */ + public function update($customerId, $attributes) + { + Util::verifyKeys(self::updateSignature(), $attributes); + $this->_validateId($customerId); + return $this->_doUpdate( + 'put', + '/customers/' . $customerId, + ['customer' => $attributes] + ); + } + + /** + * update a customer record, assuming validations will pass + * + * if calling this method in static context, customerId + * is the 2nd attribute. customerId is not sent in object context. + * returns a Customer object on success + * + * @access public + * @param string $customerId + * @param array $attributes + * @return Customer + * @throws Exception\ValidationsFailed + */ + public function updateNoValidate($customerId, $attributes) + { + $result = $this->update($customerId, $attributes); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + /** + * + * @deprecated since version 2.3.0 + * @access public + * @return string + */ + public function updateCustomerUrl() + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); + return $this->_config->baseUrl() . $this->_config->merchantPath() . + '/customers/all/update_via_transparent_redirect_request'; + } + + /** + * update a customer from a TransparentRedirect operation + * + * @deprecated since version 2.3.0 + * @access public + * @param string $queryString + * @return object + */ + public function updateFromTransparentRedirect($queryString) + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + return $this->_doUpdate( + 'post', + '/customers/all/confirm_transparent_redirect_request', + ['id' => $params['id']] + ); + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @ignore + * @access protected + * @param array $customerAttribs array of customer data + * @return void + */ + protected function _initialize($customerAttribs) + { + // set the attributes + $this->_attributes = $customerAttribs; + + // map each address into its own object + $addressArray = []; + if (isset($customerAttribs['addresses'])) { + + foreach ($customerAttribs['addresses'] AS $address) { + $addressArray[] = Address::factory($address); + } + } + $this->_set('addresses', $addressArray); + + // map each creditCard into its own object + $creditCardArray = []; + if (isset($customerAttribs['creditCards'])) { + foreach ($customerAttribs['creditCards'] AS $creditCard) { + $creditCardArray[] = CreditCard::factory($creditCard); + } + } + $this->_set('creditCards', $creditCardArray); + + // map each coinbaseAccount into its own object + $coinbaseAccountArray = []; + if (isset($customerAttribs['coinbaseAccounts'])) { + foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) { + $coinbaseAccountArray[] = CoinbaseAccount::factory($coinbaseAccount); + } + } + $this->_set('coinbaseAccounts', $coinbaseAccountArray); + + // map each paypalAccount into its own object + $paypalAccountArray = []; + if (isset($customerAttribs['paypalAccounts'])) { + foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { + $paypalAccountArray[] = PayPalAccount::factory($paypalAccount); + } + } + $this->_set('paypalAccounts', $paypalAccountArray); + + // map each applePayCard into its own object + $applePayCardArray = []; + if (isset($customerAttribs['applePayCards'])) { + foreach ($customerAttribs['applePayCards'] AS $applePayCard) { + $applePayCardArray[] = ApplePayCard::factory($applePayCard); + } + } + $this->_set('applePayCards', $applePayCardArray); + + // map each androidPayCard into its own object + $androidPayCardArray = []; + if (isset($customerAttribs['androidPayCards'])) { + foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) { + $androidPayCardArray[] = AndroidPayCard::factory($androidPayCard); + } + } + $this->_set('androidPayCards', $androidPayCardArray); + + $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts, $this->androidPayCards)); + } + + /** + * returns a string representation of the customer + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + + /** + * returns false if comparing object is not a Customer, + * or is a Customer with a different id + * + * @param object $otherCust customer to compare against + * @return boolean + */ + public function isEqual($otherCust) + { + return !($otherCust instanceof Customer) ? false : $this->id === $otherCust->id; + } + + /** + * returns an array containt all of the customer's payment methods + * + * @return array + */ + public function paymentMethods() + { + return $this->paymentMethods; + } + + /** + * returns the customer's default payment method + * + * @return CreditCard|PayPalAccount|ApplePayCard|AndroidPayCard + */ + public function defaultPaymentMethod() + { + $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree\\Customer::_defaultPaymentMethodFilter'); + return current($defaultPaymentMethods); + } + + public static function _defaultPaymentMethodFilter($paymentMethod) + { + return $paymentMethod->isDefault(); + } + + /* private class properties */ + + /** + * @access protected + * @var array registry of customer data + */ + protected $_attributes = [ + 'addresses' => '', + 'company' => '', + 'creditCards' => '', + 'email' => '', + 'fax' => '', + 'firstName' => '', + 'id' => '', + 'lastName' => '', + 'phone' => '', + 'createdAt' => '', + 'updatedAt' => '', + 'website' => '', + ]; + + /** + * sends the create request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + public function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * verifies that a valid customer id is being used + * @ignore + * @param string customer id + * @throws InvalidArgumentException + */ + private function _validateId($id = null) { + if (is_null($id)) { + throw new InvalidArgumentException( + 'expected customer id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { + throw new InvalidArgumentException( + $id . ' is an invalid customer id.' + ); + } + } + + + /* private class methods */ + + /** + * sends the update request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + private function _doUpdate($httpVerb, $subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->$httpVerb($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new Customer object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['customer'])) { + // return a populated instance of Customer + return new Result\Successful( + Customer::factory($response['customer']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected customer or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\CustomerGateway', 'Braintree_CustomerGateway'); diff --git a/lib/Braintree/CustomerSearch.php b/lib/Braintree/CustomerSearch.php index 5de6cee..3bc734e 100644 --- a/lib/Braintree/CustomerSearch.php +++ b/lib/Braintree/CustomerSearch.php @@ -1,30 +1,34 @@ _set('merchantAccount', - Braintree_MerchantAccount::factory($disbursementAttribs['merchantAccount']) + MerchantAccount::factory($disbursementAttribs['merchantAccount']) ); } } public function transactions() { - $collection = Braintree_Transaction::search(array( - Braintree_TransactionSearch::ids()->in($this->transactionIds) - )); + $collection = Transaction::search([ + TransactionSearch::ids()->in($this->transactionIds), + ]); return $collection; } @@ -33,17 +39,28 @@ public static function factory($attributes) public function __toString() { - $display = array( + $display = [ 'id', 'merchantAccountDetails', 'exceptionMessage', 'amount', 'disbursementDate', 'followUpAction', 'retry', 'success', - 'transactionIds' - ); + 'transactionIds', 'disbursementType' + ]; - $displayAttributes = array(); + $displayAttributes = []; foreach ($display AS $attrib) { $displayAttributes[$attrib] = $this->$attrib; } return __CLASS__ . '[' . - Braintree_Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) .']'; + } + + public function isDebit() + { + return $this->disbursementType == Disbursement::TYPE_DEBIT; + } + + public function isCredit() + { + return $this->disbursementType == Disbursement::TYPE_CREDIT; } } +class_alias('Braintree\Disbursement', 'Braintree_Disbursement'); diff --git a/lib/Braintree/DisbursementDetails.php b/lib/Braintree/DisbursementDetails.php index 471a163..ffc31e8 100644 --- a/lib/Braintree/DisbursementDetails.php +++ b/lib/Braintree/DisbursementDetails.php @@ -1,17 +1,12 @@ disbursementDate); } } +class_alias('Braintree\DisbursementDetails', 'Braintree_DisbursementDetails'); diff --git a/lib/Braintree/Discount.php b/lib/Braintree/Discount.php index 0c8e12e..da780d0 100644 --- a/lib/Braintree/Discount.php +++ b/lib/Braintree/Discount.php @@ -1,22 +1,21 @@ $response['discounts']); - - return Braintree_Util::extractAttributeAsArray( - $discounts, - 'discount' - ); - } +namespace Braintree; +class Discount extends Modification +{ public static function factory($attributes) { $instance = new self(); $instance->_initialize($attributes); return $instance; } + + + // static methods redirecting to gateway + + public static function all() + { + return Configuration::gateway()->discount()->all(); + } } +class_alias('Braintree\Discount', 'Braintree_Discount'); diff --git a/lib/Braintree/DiscountGateway.php b/lib/Braintree/DiscountGateway.php new file mode 100644 index 0000000..d26672a --- /dev/null +++ b/lib/Braintree/DiscountGateway.php @@ -0,0 +1,31 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function all() + { + $path = $this->_config->merchantPath() . '/discounts'; + $response = $this->_http->get($path); + + $discounts = ["discount" => $response['discounts']]; + + return Util::extractAttributeAsArray( + $discounts, + 'discount' + ); + } +} +class_alias('Braintree\DiscountGateway', 'Braintree_DiscountGateway'); diff --git a/lib/Braintree/Dispute.php b/lib/Braintree/Dispute.php new file mode 100644 index 0000000..dc17eba --- /dev/null +++ b/lib/Braintree/Dispute.php @@ -0,0 +1,177 @@ +_attributes = $disputeAttribs; + + if (isset($disputeAttribs['transaction'])) { + $transactionDetails = new Dispute\TransactionDetails($disputeAttribs['transaction']); + $this->_set('transactionDetails', $transactionDetails); + $this->_set('transaction', $transactionDetails); + } + + if (isset($disputeAttribs['evidence'])) { + $evidenceArray = array_map(function($evidence) { + return new Dispute\EvidenceDetails($evidence); + }, $disputeAttribs['evidence']); + $this->_set('evidence', $evidenceArray); + } + + if (isset($disputeAttribs['statusHistory'])) { + $statusHistoryArray = array_map(function($statusHistory) { + return new Dispute\StatusHistoryDetails($statusHistory); + }, $disputeAttribs['statusHistory']); + $this->_set('statusHistory', $statusHistoryArray); + } + + if (isset($disputeAttribs['transaction'])) { + $this->_set('transaction', + new Dispute\TransactionDetails($disputeAttribs['transaction']) + ); + } + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + public function __toString() + { + $display = [ + 'amount', 'reason', 'status', + 'replyByDate', 'receivedDate', 'currencyIsoCode' + ]; + + $displayAttributes = []; + foreach ($display AS $attrib) { + $displayAttributes[$attrib] = $this->$attrib; + } + return __CLASS__ . '[' . + Util::attributesToString($displayAttributes) .']'; + } + + /** + * Accepts a dispute, given a dispute ID + * + * @param string $id + */ + public static function accept($id) + { + return Configuration::gateway()->dispute()->accept($id); + } + + /** + * Adds file evidence to a dispute, given a dispute ID and a document ID + * + * @param string $disputeId + * @param string $documentIdOrRequest + */ + public static function addFileEvidence($disputeId, $documentIdOrRequest) + { + return Configuration::gateway()->dispute()->addFileEvidence($disputeId, $documentIdOrRequest); + } + + /** + * Adds text evidence to a dispute, given a dispute ID and content + * + * @param string $id + * @param string $contentOrRequest + */ + public static function addTextEvidence($id, $contentOrRequest) + { + return Configuration::gateway()->dispute()->addTextEvidence($id, $contentOrRequest); + } + + /** + * Finalize a dispute, given a dispute ID + * + * @param string $id + */ + public static function finalize($id) + { + return Configuration::gateway()->dispute()->finalize($id); + } + + /** + * Find a dispute, given a dispute ID + * + * @param string $id + */ + public static function find($id) + { + return Configuration::gateway()->dispute()->find($id); + } + + /** + * Remove evidence from a dispute, given a dispute ID and evidence ID + * + * @param string $disputeId + * @param string $evidenceId + */ + public static function removeEvidence($disputeId, $evidenceId) + { + return Configuration::gateway()->dispute()->removeEvidence($disputeId, $evidenceId); + } + + /** + * Search for Disputes, given a DisputeSearch query + * + * @param DisputeSearch $query + */ + public static function search($query) + { + return Configuration::gateway()->dispute()->search($query); + } +} +class_alias('Braintree\Dispute', 'Braintree_Dispute'); diff --git a/lib/Braintree/Dispute/EvidenceDetails.php b/lib/Braintree/Dispute/EvidenceDetails.php new file mode 100644 index 0000000..14fa9d2 --- /dev/null +++ b/lib/Braintree/Dispute/EvidenceDetails.php @@ -0,0 +1,31 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /* public class methods */ + + /** + * Accepts a dispute, given a dispute ID + * + * @param string $id + */ + public function accept($id) + { + try { + if (trim($id) == "") { + throw new Exception\NotFound(); + } + + $path = $this->_config->merchantPath() . '/disputes/' . $id . '/accept'; + $response = $this->_http->put($path); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + return new Result\Successful(); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('dispute with id "' . $id . '" not found'); + } + } + + /** + * Adds file evidence to a dispute, given a dispute ID and a document ID + * + * @param string $disputeId + * @param string $documentIdOrRequest + */ + public function addFileEvidence($disputeId, $documentIdOrRequest) + { + $request = is_array($documentIdOrRequest) ? $documentIdOrRequest : ['documentId' => $documentIdOrRequest]; + + if (trim($disputeId) == "") { + throw new Exception\NotFound('dispute with id "' . $disputeId . '" not found'); + } + + if (trim($request['documentId']) == "") { + throw new Exception\NotFound('document with id "' . $request['documentId'] . '" not found'); + } + + try { + if (array_key_exists('category', $request)) { + if (trim($request['category']) == "") { + throw new InvalidArgumentException('category cannot be blank'); + } + } + + $request['document_upload_id'] = $request['documentId']; + unset($request['documentId']); + + $path = $this->_config->merchantPath() . '/disputes/' . $disputeId . '/evidence'; + $response = $this->_http->post($path, ['evidence' => $request]); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + if (isset($response['evidence'])) { + $evidence = new Dispute\EvidenceDetails($response['evidence']); + return new Result\Successful($evidence); + } + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('dispute with id "' . $disputeId . '" not found'); + } + } + + /** + * Adds text evidence to a dispute, given a dispute ID and content + * + * @param string $id + * @param string $content + */ + public function addTextEvidence($id, $contentOrRequest) + { + $request = is_array($contentOrRequest) ? $contentOrRequest : ['content' => $contentOrRequest]; + if (trim($request['content']) == "") { + throw new InvalidArgumentException('content cannot be blank'); + } + + try { + $evidence = [ + 'comments' => $request['content'], + ]; + + if (trim($id) == "") { + throw new Exception\NotFound(); + } + + if (array_key_exists('tag', $request)) { + $evidence['category'] = $request['tag']; + } + + if (array_key_exists('category', $request)) { + if (trim($request['category']) == "") { + throw new InvalidArgumentException('category cannot be blank'); + } + $evidence['category'] = $request['category']; + } + + if (array_key_exists('sequenceNumber', $request)) { + if (trim($request['sequenceNumber']) == "") { + throw new InvalidArgumentException('sequenceNumber cannot be blank'); + } else if ((string)(int)($request['sequenceNumber']) != $request['sequenceNumber']) { + throw new InvalidArgumentException('sequenceNumber must be an integer'); + } + $evidence['sequenceNumber'] = (int)$request['sequenceNumber']; + } + + $path = $this->_config->merchantPath() . '/disputes/' . $id . '/evidence'; + $response = $this->_http->post($path, [ + 'evidence' => $evidence + ]); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + if (isset($response['evidence'])) { + $evidence = new Dispute\EvidenceDetails($response['evidence']); + return new Result\Successful($evidence); + } + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('dispute with id "' . $id . '" not found'); + } + } + + /** + * Finalize a dispute, given a dispute ID + * + * @param string $id + */ + public function finalize($id) + { + try { + if (trim($id) == "") { + throw new Exception\NotFound(); + } + + $path = $this->_config->merchantPath() . '/disputes/' . $id . '/finalize'; + $response = $this->_http->put($path); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + return new Result\Successful(); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('dispute with id "' . $id . '" not found'); + } + } + + /** + * Find a dispute, given a dispute ID + * + * @param string $id + */ + public function find($id) + { + if (trim($id) == "") { + throw new Exception\NotFound('dispute with id "' . $id . '" not found'); + } + + try { + $path = $this->_config->merchantPath() . '/disputes/' . $id; + $response = $this->_http->get($path); + return Dispute::factory($response['dispute']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('dispute with id "' . $id . '" not found'); + } + } + + /** + * Remove evidence from a dispute, given a dispute ID and evidence ID + * + * @param string $disputeId + * @param string $evidenceId + */ + public function removeEvidence($disputeId, $evidenceId) + { + try { + if (trim($disputeId) == "" || trim($evidenceId) == "") { + throw new Exception\NotFound(); + } + + $path = $this->_config->merchantPath() . '/disputes/' . $disputeId . '/evidence/' . $evidenceId; + $response = $this->_http->delete($path); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + return new Result\Successful(); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('evidence with id "' . $evidenceId . '" for dispute with id "' . $disputeId . '" not found'); + } + } + + /** + * Search for Disputes, given a DisputeSearch query + * + * @param DisputeSearch $query + */ + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + $pager = [ + 'object' => $this, + 'method' => 'fetchDisputes', + 'query' => $criteria + ]; + return new PaginatedCollection($pager); + } + + public function fetchDisputes($query, $page) + { + $response = $this->_http->post($this->_config->merchantPath() . '/disputes/advanced_search?page=' . $page, [ + 'search' => $query + ]); + $body = $response['disputes']; + $disputes = Util::extractattributeasarray($body, 'dispute'); + $totalItems = $body['totalItems'][0]; + $pageSize = $body['pageSize'][0]; + return new PaginatedResult($totalItems, $pageSize, $disputes); + } +} +class_alias('Braintree\DisputeGateway', 'Braintree_DisputeGateway'); diff --git a/lib/Braintree/DisputeSearch.php b/lib/Braintree/DisputeSearch.php new file mode 100644 index 0000000..b97c463 --- /dev/null +++ b/lib/Braintree/DisputeSearch.php @@ -0,0 +1,90 @@ + Braintree\DocumentUpload::EVIDENCE_DOCUMENT, + * "file" => $pngFile + * ]); + * + * For more information on DocumentUploads, see https://developers.braintreepayments.com/reference/request/document_upload/create + */ +class DocumentUpload extends Base +{ + /* DocumentUpload Kind */ + const EVIDENCE_DOCUMENT = "evidence_document"; + + protected function _initialize($documentUploadAttribs) + { + $this->_attributes = $documentUploadAttribs; + } + + /** + * Creates a DocumentUpload object + * @param kind The kind of document + * @param file The open file to upload + * @throws InvalidArgumentException if the params are not expected + */ + public static function create($params) + { + return Configuration::gateway()->documentUpload()->create($params); + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } +} +class_alias('Braintree\DocumentUpload', 'Braintree_DocumentUpload'); diff --git a/lib/Braintree/DocumentUploadGateway.php b/lib/Braintree/DocumentUploadGateway.php new file mode 100644 index 0000000..2839968 --- /dev/null +++ b/lib/Braintree/DocumentUploadGateway.php @@ -0,0 +1,81 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /* public class methods */ + + /** + * Accepts a dispute, given a dispute ID + * + * @param string $id + */ + public function create($params) + { + Util::verifyKeys(self::createSignature(), $params); + + $file = $params['file']; + + if (!is_resource($file)) { + throw new InvalidArgumentException('file must be a stream resource'); + } + + $payload = [ + 'document_upload[kind]' => $params['kind'] + ]; + $path = $this->_config->merchantPath() . '/document_uploads/'; + $response = $this->_http->postMultipart($path, $payload, $file); + + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } + + if (isset($response['documentUpload'])) { + $documentUpload = DocumentUpload::factory($response['documentUpload']); + return new Result\Successful($documentUpload); + } + } + + public static function createSignature() + { + return [ + 'file', 'kind' + ]; + } +} +class_alias('Braintree\DocumentUploadGateway', 'Braintree_DocumentUploadGateway'); diff --git a/lib/Braintree/EndsWithNode.php b/lib/Braintree/EndsWithNode.php new file mode 100644 index 0000000..edccec2 --- /dev/null +++ b/lib/Braintree/EndsWithNode.php @@ -0,0 +1,23 @@ +name = $name; + $this->searchTerms = []; + } + + public function endsWith($value) + { + $this->searchTerms["ends_with"] = strval($value); + return $this; + } + + public function toParam() + { + return $this->searchTerms; + } +} +class_alias('Braintree\EndsWithNode', 'Braintree_EndsWithNode'); diff --git a/lib/Braintree/EqualityNode.php b/lib/Braintree/EqualityNode.php index 68c10b5..d91e1eb 100644 --- a/lib/Braintree/EqualityNode.php +++ b/lib/Braintree/EqualityNode.php @@ -1,6 +1,7 @@ _errors = - new Braintree_Error_ValidationErrorCollection($errorData); + new ValidationErrorCollection($errorData); } + /** + * Return count of items in collection + * Implements countable + * + * @return integer + */ + public function count() + { + return $this->deepSize(); + } /** * Returns all of the validation errors at all levels of nesting in a single, flat array. @@ -77,10 +81,10 @@ public function onHtmlField($field) $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY); $errors = $this; foreach(array_slice($pieces, 0, -1) as $key) { - $errors = $errors->forKey(Braintree_Util::delimiterToCamelCase($key)); - if (!isset($errors)) { return array(); } + $errors = $errors->forKey(Util::delimiterToCamelCase($key)); + if (!isset($errors)) { return []; } } - $finalKey = Braintree_Util::delimiterToCamelCase(end($pieces)); + $finalKey = Util::delimiterToCamelCase(end($pieces)); return $errors->onAttribute($finalKey); } @@ -88,7 +92,7 @@ public function onHtmlField($field) * Returns the errors at the given nesting level (see forKey) in a single, flat array: * * - * $result = Braintree_Customer::create(...); + * $result = Customer::create(...); * $customerErrors = $result->errors->forKey('customer')->shallowAll(); * */ @@ -116,3 +120,4 @@ public function __toString() return sprintf('%s', $this->_errors); } } +class_alias('Braintree\Error\ErrorCollection', 'Braintree_Error_ErrorCollection'); diff --git a/lib/Braintree/Error/Validation.php b/lib/Braintree/Error/Validation.php index 8253ae6..79a4cc1 100644 --- a/lib/Braintree/Error/Validation.php +++ b/lib/Braintree/Error/Validation.php @@ -1,11 +1,7 @@ == More information == * - * For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors} + * For more detailed information on Validation errors, see {@link https://developers.braintreepayments.com/reference/general/validation-errors/overview/php https://developers.braintreepayments.com/reference/general/validation-errors/overview/php} * * @package Braintree * @subpackage Error - * @copyright 2010 Braintree Payment Solutions * * @property-read string $attribute * @property-read string $code * @property-read string $message */ -class Braintree_Error_Validation +class Validation { - private $_attribute; - private $_code; - private $_message; + private $_attribute; + private $_code; + private $_message; /** * @ignore @@ -42,13 +37,13 @@ public function __construct($attributes) * @ignore * @access protected * @param array $attributes array of properties to set - single level - * @return none + * @return void */ private function _initializeFromArray($attributes) { foreach($attributes AS $name => $value) { $varName = "_$name"; - $this->$varName = Braintree_Util::delimiterToCamelCase($value, '_'); + $this->$varName = Util::delimiterToCamelCase($value, '_'); } } @@ -62,3 +57,4 @@ public function __get($name) return isset($this->$varName) ? $this->$varName : null; } } +class_alias('Braintree\Error\Validation', 'Braintree_Error_Validation'); diff --git a/lib/Braintree/Error/ValidationErrorCollection.php b/lib/Braintree/Error/ValidationErrorCollection.php index 5125c90..ff3683e 100644 --- a/lib/Braintree/Error/ValidationErrorCollection.php +++ b/lib/Braintree/Error/ValidationErrorCollection.php @@ -1,30 +1,25 @@ == More information == * - * For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors} + * For more detailed information on Validation errors, see {@link https://developers.braintreepayments.com/reference/general/validation-errors/overview/php https://developers.braintreepayments.com/reference/general/validation-errors/overview/php} * * @package Braintree * @subpackage Error - * @copyright 2010 Braintree Payment Solutions * * @property-read array $errors * @property-read array $nested */ -class Braintree_Error_ValidationErrorCollection extends Braintree_Collection +class ValidationErrorCollection extends Collection { - private $_errors = array(); - private $_nested = array(); + private $_errors = []; + private $_nested = []; /** * @ignore @@ -35,17 +30,17 @@ public function __construct($data) // map errors to new collections recursively if ($key == 'errors') { foreach ($errorData AS $error) { - $this->_errors[] = new Braintree_Error_Validation($error); + $this->_errors[] = new Validation($error); } } else { - $this->_nested[$key] = new Braintree_Error_ValidationErrorCollection($errorData); + $this->_nested[$key] = new ValidationErrorCollection($errorData); } } public function deepAll() { - $validationErrors = array_merge(array(), $this->_errors); + $validationErrors = array_merge([], $this->_errors); foreach($this->_nested as $nestedErrors) { $validationErrors = array_merge($validationErrors, $nestedErrors->deepAll()); @@ -75,7 +70,7 @@ public function forKey($key) public function onAttribute($attribute) { - $matches = array(); + $matches = []; foreach ($this->_errors AS $key => $error) { if($error->attribute == $attribute) { $matches[] = $error; @@ -105,7 +100,7 @@ public function __get($name) */ public function __toString() { - $output = array(); + $output = []; // TODO: implement scope if (!empty($this->_errors)) { @@ -133,3 +128,4 @@ private function _inspect($errors, $scope = null) return $eOutput; } } +class_alias('Braintree\Error\ValidationErrorCollection', 'Braintree_Error_ValidationErrorCollection'); diff --git a/lib/Braintree/EuropeBankAccount.php b/lib/Braintree/EuropeBankAccount.php new file mode 100644 index 0000000..b661e70 --- /dev/null +++ b/lib/Braintree/EuropeBankAccount.php @@ -0,0 +1,67 @@ +== More information == + * + * See {@link https://developers.braintreepayments.com/javascript+php}
+ * + * @package Braintree + * @category Resources + * + * @property-read string $account-holder-name + * @property-read string $bic + * @property-read string $customerId + * @property-read string $default + * @property-read string $image-url + * @property-read string $mandate-reference-number + * @property-read string $masked-iban + * @property-read string $token + */ +class EuropeBankAccount extends Base +{ + + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * factory method: returns an instance of EuropeBankAccount + * to the requesting method, with populated properties + * + * @ignore + * @return EuropeBankAccount + */ + public static function factory($attributes) + { + $defaultAttributes = [ + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $europeBankAccountAttribs array of EuropeBankAccount properties + * @return void + */ + protected function _initialize($europeBankAccountAttribs) + { + $this->_attributes = $europeBankAccountAttribs; + } +} +class_alias('Braintree\EuropeBankAccount', 'Braintree_EuropeBankAccount'); diff --git a/lib/Braintree/Exception.php b/lib/Braintree/Exception.php index 40ec119..58d0805 100644 --- a/lib/Braintree/Exception.php +++ b/lib/Braintree/Exception.php @@ -1,20 +1,13 @@ _initialize($attributes); + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } + + /** + * returns a string representation of the facilitated details + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + +} +class_alias('Braintree\FacilitatedDetails', 'Braintree_FacilitatedDetails'); diff --git a/lib/Braintree/FacilitatorDetails.php b/lib/Braintree/FacilitatorDetails.php new file mode 100644 index 0000000..eda4fcc --- /dev/null +++ b/lib/Braintree/FacilitatorDetails.php @@ -0,0 +1,30 @@ +_initialize($attributes); + + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } + + /** + * returns a string representation of the facilitator details + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + +} +class_alias('Braintree\FacilitatorDetails', 'Braintree_FacilitatorDetails'); diff --git a/lib/Braintree/Gateway.php b/lib/Braintree/Gateway.php new file mode 100644 index 0000000..701a599 --- /dev/null +++ b/lib/Braintree/Gateway.php @@ -0,0 +1,278 @@ +config = $config; + } + + /** + * + * @return AddOnGateway + */ + public function addOn() + { + return new AddOnGateway($this); + } + + /** + * + * @return AddressGateway + */ + public function address() + { + return new AddressGateway($this); + } + + /** + * + * @return ApplePayGateway + */ + public function applePay() + { + return new ApplePayGateway($this); + } + + /** + * + * @return ClientTokenGateway + */ + public function clientToken() + { + return new ClientTokenGateway($this); + } + + /** + * + * @return CreditCardGateway + */ + public function creditCard() + { + return new CreditCardGateway($this); + } + + /** + * + * @return CreditCardVerificationGateway + */ + public function creditCardVerification() + { + return new CreditCardVerificationGateway($this); + } + + /** + * + * @return CustomerGateway + */ + public function customer() + { + return new CustomerGateway($this); + } + + /** + * + * @return DiscountGateway + */ + public function discount() + { + return new DiscountGateway($this); + } + + /** + * + * @return DisputeGateway + */ + public function dispute() + { + return new DisputeGateway($this); + } + + /** + * + * @return DocumentUploadGateway + */ + public function documentUpload() + { + return new DocumentUploadGateway($this); + } + + /** + * + * @return MerchantGateway + */ + public function merchant() + { + return new MerchantGateway($this); + } + + /** + * + * @return MerchantAccountGateway + */ + public function merchantAccount() + { + return new MerchantAccountGateway($this); + } + + /** + * + * @return OAuthGateway + */ + public function oauth() + { + return new OAuthGateway($this); + } + + /** + * + * @return PaymentMethodGateway + */ + public function paymentMethod() + { + return new PaymentMethodGateway($this); + } + + /** + * + * @return PaymentMethodNonceGateway + */ + public function paymentMethodNonce() + { + return new PaymentMethodNonceGateway($this); + } + + /** + * + * @return PayPalAccountGateway + */ + public function payPalAccount() + { + return new PayPalAccountGateway($this); + } + + /** + * + * @return PlanGateway + */ + public function plan() + { + return new PlanGateway($this); + } + + /** + * + * @return SettlementBatchSummaryGateway + */ + public function settlementBatchSummary() + { + return new SettlementBatchSummaryGateway($this); + } + + /** + * + * @return SubscriptionGateway + */ + public function subscription() + { + return new SubscriptionGateway($this); + } + + /** + * + * @return TestingGateway + */ + public function testing() + { + return new TestingGateway($this); + } + + /** + * + * @return TransactionGateway + */ + public function transaction() + { + return new TransactionGateway($this); + } + + /** + * + * @return TransactionLineItemGateway + */ + public function transactionLineItem() + { + return new TransactionLineItemGateway($this); + } + + /** + * + * @return TransparentRedirectGateway + */ + public function transparentRedirect() + { + return new TransparentRedirectGateway($this); + } + + /** + * + * @return UsBankAccountGateway + */ + public function usBankAccount() + { + return new UsBankAccountGateway($this); + } + + /** + * + * @return UsBankAccountVerificationGateway + */ + public function usBankAccountVerification() + { + return new UsBankAccountVerificationGateway($this); + } + + /** + * + * @return IdealPaymentGateway + */ + public function idealPayment() + { + return new IdealPaymentGateway($this); + } + + /** + * + * @return WebhookNotificationGateway + */ + public function webhookNotification() + { + return new WebhookNotificationGateway($this); + } + + /** + * + * @return WebhookTestingGateway + */ + public function webhookTesting() + { + return new WebhookTestingGateway($this); + } +} +class_alias('Braintree\Gateway', 'Braintree_Gateway'); diff --git a/lib/Braintree/GrantedPaymentInstrumentUpdate.php b/lib/Braintree/GrantedPaymentInstrumentUpdate.php new file mode 100644 index 0000000..551b0c8 --- /dev/null +++ b/lib/Braintree/GrantedPaymentInstrumentUpdate.php @@ -0,0 +1,73 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $grantOwnerMerchantId + * @property-read string $grantRecipientMerchantId + * @property-read string $paymentMethodNonce + * @property-read string $token + * @property-read string $updatedFields + */ +class GrantedPaymentInstrumentUpdate extends Base +{ + /** + * factory method: returns an instance of GrantedPaymentInstrumentUpdate + * to the requesting method, with populated properties + * + * @ignore + * @return GrantedPaymentInstrumentUpdate + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $GrantedPaymentInstrumentAttribs array of grantedPaymentInstrumentUpdate data + * @return void + */ + protected function _initialize($grantedPaymentInstrumentUpdateAttribs) + { + // set the attributes + $this->_attributes = $grantedPaymentInstrumentUpdateAttribs; + + $paymentMethodNonce = isset($grantedPaymentInstrumentUpdateAttribs['paymentMethodNonce']) ? + GrantedPaymentInstrumentUpdate::factory($grantedPaymentInstrumentUpdateAttribs['paymentMethodNonce']) : + null; + $this->_set('paymentMethodNonce', $paymentMethodNonce); + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } +} +class_alias('Braintree\GrantedPaymentInstrumentUpdate', 'Braintree_GrantedPaymentInstrumentUpdate'); diff --git a/lib/Braintree/GraphQL.php b/lib/Braintree/GraphQL.php new file mode 100644 index 0000000..488d6fe --- /dev/null +++ b/lib/Braintree/GraphQL.php @@ -0,0 +1,44 @@ + $definition]; + if ($variables) { + $graphQLRequest["variables"] = $variables; + } + + $response = $this->_doUrlRequest('POST', $this->_config->graphQLBaseUrl(), json_encode($graphQLRequest), null, $this->graphQLHeaders()); + + $result = json_decode($response["body"], true); + Util::throwGraphQLResponseException($result); + + return $result; + } +} + +class_alias('Braintree\GraphQL', 'Braintree_GraphQL'); diff --git a/lib/Braintree/Http.php b/lib/Braintree/Http.php index fb05985..616be51 100644 --- a/lib/Braintree/Http.php +++ b/lib/Braintree/Http.php @@ -1,104 +1,273 @@ _config = $config; + } + + public function delete($path, $params = null) { - $response = self::_doRequest('DELETE', $path); - if($response['status'] === 200) { + $response = $this->_doRequest('DELETE', $path, $this->_buildXml($params)); + $responseCode = $response['status']; + if ($responseCode === 200 || $responseCode === 204) { return true; + } else if ($responseCode === 422) { + return Xml::buildArrayFromXml($response['body']); + } else { + Util::throwStatusCodeException($response['status']); + } + } + + public function get($path) + { + $response = $this->_doRequest('GET', $path); + if ($response['status'] === 200) { + return Xml::buildArrayFromXml($response['body']); } else { - Braintree_Util::throwStatusCodeException($response['status']); + Util::throwStatusCodeException($response['status']); } } - public static function get($path) + public function post($path, $params = null) { - $response = self::_doRequest('GET', $path); - if($response['status'] === 200) { - return Braintree_Xml::buildArrayFromXml($response['body']); + $response = $this->_doRequest('POST', $path, $this->_buildXml($params)); + $responseCode = $response['status']; + if ($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) { + return Xml::buildArrayFromXml($response['body']); } else { - Braintree_Util::throwStatusCodeException($response['status']); + Util::throwStatusCodeException($responseCode); } } - public static function post($path, $params = null) + public function postMultipart($path, $params, $file) { - $response = self::_doRequest('POST', $path, self::_buildXml($params)); + $headers = [ + 'User-Agent: Braintree PHP Library ' . Version::get(), + 'X-ApiVersion: ' . Configuration::API_VERSION + ]; + $response = $this->_doRequest('POST', $path, $params, $file, $headers); $responseCode = $response['status']; - if($responseCode === 200 || $responseCode === 201 || $responseCode === 422) { - return Braintree_Xml::buildArrayFromXml($response['body']); + if ($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) { + return Xml::buildArrayFromXml($response['body']); } else { - Braintree_Util::throwStatusCodeException($responseCode); + Util::throwStatusCodeException($responseCode); } } - public static function put($path, $params = null) + public function put($path, $params = null) { - $response = self::_doRequest('PUT', $path, self::_buildXml($params)); + $response = $this->_doRequest('PUT', $path, $this->_buildXml($params)); $responseCode = $response['status']; - if($responseCode === 200 || $responseCode === 201 || $responseCode === 422) { - return Braintree_Xml::buildArrayFromXml($response['body']); + if ($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) { + return Xml::buildArrayFromXml($response['body']); } else { - Braintree_Util::throwStatusCodeException($responseCode); + Util::throwStatusCodeException($responseCode); } } - private static function _buildXml($params) + private function _buildXml($params) { - return empty($params) ? null : Braintree_Xml::buildXmlFromArray($params); + return empty($params) ? null : Xml::buildXmlFromArray($params); } - private static function _doRequest($httpVerb, $path, $requestBody = null) + private function _getHeaders() { - return self::_doUrlRequest($httpVerb, Braintree_Configuration::merchantUrl() . $path, $requestBody); + return [ + 'Accept: application/xml', + ]; } - public static function _doUrlRequest($httpVerb, $url, $requestBody = null) + private function _getAuthorization() + { + if ($this->_useClientCredentials) { + return [ + 'user' => $this->_config->getClientId(), + 'password' => $this->_config->getClientSecret(), + ]; + } else if ($this->_config->isAccessToken()) { + return [ + 'token' => $this->_config->getAccessToken(), + ]; + } else { + return [ + 'user' => $this->_config->getPublicKey(), + 'password' => $this->_config->getPrivateKey(), + ]; + } + } + + public function useClientCredentials() + { + $this->_useClientCredentials = true; + } + + private function _doRequest($httpVerb, $path, $requestBody = null, $file = null, $headers = null) + { + return $this->_doUrlRequest($httpVerb, $this->_config->baseUrl() . $path, $requestBody, $file, $headers); + } + + public function _doUrlRequest($httpVerb, $url, $requestBody = null, $file = null, $customHeaders = null) { $curl = curl_init(); - curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_TIMEOUT, $this->_config->timeout()); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb); curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); - curl_setopt($curl, CURLOPT_HTTPHEADER, array( - 'Accept: application/xml', - 'Content-Type: application/xml', - 'User-Agent: Braintree PHP Library ' . Braintree_Version::get(), - 'X-ApiVersion: ' . Braintree_Configuration::API_VERSION - )); - curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_setopt($curl, CURLOPT_USERPWD, Braintree_Configuration::publicKey() . ':' . Braintree_Configuration::privateKey()); - // curl_setopt($curl, CURLOPT_VERBOSE, true); - if (Braintree_Configuration::sslOn()) { + + if ($this->_config->acceptGzipEncoding()) { + curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); + } + if ($this->_config->sslVersion()) { + curl_setopt($curl, CURLOPT_SSLVERSION, $this->_config->sslVersion()); + } + + $headers = []; + if ($customHeaders) { + $headers = $customHeaders; + } else { + $headers = $this->_getHeaders($curl); + $headers[] = 'User-Agent: Braintree PHP Library ' . Version::get(); + $headers[] = 'X-ApiVersion: ' . Configuration::API_VERSION; + $headers[] = 'Content-Type: application/xml'; + } + + $authorization = $this->_getAuthorization(); + if (isset($authorization['user'])) { + curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($curl, CURLOPT_USERPWD, $authorization['user'] . ':' . $authorization['password']); + } else if (isset($authorization['token'])) { + $headers[] = 'Authorization: Bearer ' . $authorization['token']; + } + + if ($this->_config->sslOn()) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); - curl_setopt($curl, CURLOPT_CAINFO, Braintree_Configuration::caFile()); + curl_setopt($curl, CURLOPT_CAINFO, $this->getCaFile()); } - if(!empty($requestBody)) { + if (!empty($file)) { + $boundary = "---------------------" . md5(mt_rand() . microtime()); + $headers[] = "Content-Type: multipart/form-data; boundary={$boundary}"; + $this->prepareMultipart($curl, $requestBody, $file, $boundary); + } else if (!empty($requestBody)) { curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody); } + if ($this->_config->isUsingProxy()) { + $proxyHost = $this->_config->getProxyHost(); + $proxyPort = $this->_config->getProxyPort(); + $proxyType = $this->_config->getProxyType(); + $proxyUser = $this->_config->getProxyUser(); + $proxyPwd= $this->_config->getProxyPassword(); + curl_setopt($curl, CURLOPT_PROXY, $proxyHost . ':' . $proxyPort); + if (!empty($proxyType)) { + curl_setopt($curl, CURLOPT_PROXYTYPE, $proxyType); + } + if ($this->_config->isAuthenticatedProxy()) { + curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPwd); + } + } + + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $error_code = curl_errno($curl); + $error = curl_error($curl); + + if ($error_code == 28 && $httpStatus == 0) { + throw new Exception\Timeout(); + } + curl_close($curl); - if (Braintree_Configuration::sslOn()) { + if ($this->_config->sslOn()) { if ($httpStatus == 0) { - throw new Braintree_Exception_SSLCertificate(); + throw new Exception\SSLCertificate($error, $error_code); + } + } else if ($error_code) { + throw new Exception\Connection($error, $error_code); + } + + return ['status' => $httpStatus, 'body' => $response]; + } + + function prepareMultipart($ch, $requestBody, $file, $boundary) { + $disallow = ["\0", "\"", "\r", "\n"]; + $fileInfo = new finfo(FILEINFO_MIME_TYPE); + $filePath = stream_get_meta_data($file)['uri']; + $data = file_get_contents($filePath); + $mimeType = $fileInfo->buffer($data); + + // build normal parameters + foreach ($requestBody as $k => $v) { + $k = str_replace($disallow, "_", $k); + $body[] = implode("\r\n", [ + "Content-Disposition: form-data; name=\"{$k}\"", + "", + filter_var($v), + ]); + } + + // build file parameter + $splitFilePath = explode(DIRECTORY_SEPARATOR, $filePath); + $filePath = end($splitFilePath); + $filePath = str_replace($disallow, "_", $filePath); + $body[] = implode("\r\n", [ + "Content-Disposition: form-data; name=\"file\"; filename=\"{$filePath}\"", + "Content-Type: {$mimeType}", + "", + $data, + ]); + + // add boundary for each parameters + array_walk($body, function (&$part) use ($boundary) { + $part = "--{$boundary}\r\n{$part}"; + }); + + // add final boundary + $body[] = "--{$boundary}--"; + $body[] = ""; + + // set options + return curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => implode("\r\n", $body) + ]); + } + + private function getCaFile() + { + static $memo; + + if ($memo === null) { + $caFile = $this->_config->caFile(); + + if (substr($caFile, 0, 7) !== 'phar://') { + return $caFile; } + + $extractedCaFile = sys_get_temp_dir() . '/api_braintreegateway_com.ca.crt'; + + if (!file_exists($extractedCaFile) || sha1_file($extractedCaFile) != sha1_file($caFile)) { + if (!copy($caFile, $extractedCaFile)) { + throw new Exception\SSLCaFileNotFound(); + } + } + $memo = $extractedCaFile; } - return array('status' => $httpStatus, 'body' => $response); + + return $memo; } } +class_alias('Braintree\Http', 'Braintree_Http'); diff --git a/lib/Braintree/IbanBankAccount.php b/lib/Braintree/IbanBankAccount.php new file mode 100644 index 0000000..8e53563 --- /dev/null +++ b/lib/Braintree/IbanBankAccount.php @@ -0,0 +1,57 @@ +_attributes) . ']'; + } + + /** + * sets instance properties from an array of values + * + * @ignore + * @access protected + * @param array $ibanAttribs array of ibanBankAccount data + * @return void + */ + protected function _initialize($ibanAttribs) + { + // set the attributes + $this->_attributes = $ibanAttribs; + } + + /** + * factory method: returns an instance of IbanBankAccount + * to the requesting method, with populated properties + * @ignore + * @return IbanBankAccount + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } +} +class_alias('Braintree\IbanBankAccount', 'Braintree_IbanBankAccount'); diff --git a/lib/Braintree/IdealPayment.php b/lib/Braintree/IdealPayment.php new file mode 100644 index 0000000..2ada135 --- /dev/null +++ b/lib/Braintree/IdealPayment.php @@ -0,0 +1,92 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $id + * @property-read string $idealTransactionId + * @property-read string $currency + * @property-read string $amount + * @property-read string $status + * @property-read string $orderId + * @property-read string $issuer + * @property-read string $ibanBankAccount + */ +class IdealPayment extends Base +{ + /** + * factory method: returns an instance of IdealPayment + * to the requesting method, with populated properties + * + * @ignore + * @return IdealPayment + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $idealPaymentAttribs array of idealPayment data + * @return void + */ + protected function _initialize($idealPaymentAttribs) + { + // set the attributes + $this->_attributes = $idealPaymentAttribs; + + $ibanBankAccount = isset($idealPaymentAttribs['ibanBankAccount']) ? + IbanBankAccount::factory($idealPaymentAttribs['ibanBankAccount']) : + null; + $this->_set('ibanBankAccount', $ibanBankAccount); + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } + + + // static methods redirecting to gateway + + public static function find($idealPaymentId) + { + return Configuration::gateway()->idealPayment()->find($idealPaymentId); + } + + public static function sale($idealPaymentId, $transactionAttribs) + { + $transactionAttribs['options'] = [ + 'submitForSettlement' => true + ]; + return Configuration::gateway()->idealPayment()->sale($idealPaymentId, $transactionAttribs); + } +} +class_alias('Braintree\IdealPayment', 'Braintree_IdealPayment'); diff --git a/lib/Braintree/IdealPaymentGateway.php b/lib/Braintree/IdealPaymentGateway.php new file mode 100644 index 0000000..258bc46 --- /dev/null +++ b/lib/Braintree/IdealPaymentGateway.php @@ -0,0 +1,104 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class IdealPaymentGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /** + * find an IdealPayment by id + * + * @access public + * @param string $idealPaymentId + * @return IdealPayment + * @throws Exception\NotFound + */ + public function find($idealPaymentId) + { + try { + $path = $this->_config->merchantPath() . '/ideal_payments/' . $idealPaymentId; + $response = $this->_http->get($path); + return IdealPayment::factory($response['idealPayment']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'iDEAL Payment with id ' . $idealPaymentId . ' not found' + ); + } + } + + /** + * create a new sale for the current IdealPayment + * + * @param string $idealPaymentId + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + * @see Transaction::sale() + */ + public function sale($idealPaymentId, $transactionAttribs) + { + return Transaction::sale( + array_merge( + $transactionAttribs, + ['paymentMethodNonce' => $idealPaymentId] + ) + ); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new IdealPayment object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['idealPayment'])) { + // return a populated instance of IdealPayment + return new Result\Successful( + IdealPayment::factory($response['idealPayment']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + 'Expected Ideal Payment or apiErrorResponse' + ); + } + } +} +class_alias('Braintree\IdealPaymentGateway', 'Braintree_IdealPaymentGateway'); diff --git a/lib/Braintree/Instance.php b/lib/Braintree/Instance.php index c048254..ba0d272 100644 --- a/lib/Braintree/Instance.php +++ b/lib/Braintree/Instance.php @@ -1,25 +1,18 @@ _attributes); - return get_class($this) .'['.$objOutput.']'; + $objOutput = Util::implodeAssociativeArray($this->_attributes); + return get_class($this) .'[' . $objOutput . ']'; } /** * initializes instance properties from the keys/values of an array * @ignore * @access protected * @param $aAttribs array of properties to set - single level - * @return none + * @return void */ private function _initializeFromArray($attributes) { @@ -79,3 +71,4 @@ private function _initializeFromArray($attributes) } } +class_alias('Braintree\Instance', 'Braintree_Instance'); diff --git a/lib/Braintree/IsNode.php b/lib/Braintree/IsNode.php index 321fbb3..6db01b0 100644 --- a/lib/Braintree/IsNode.php +++ b/lib/Braintree/IsNode.php @@ -1,21 +1,24 @@ name = $name; - $this->searchTerms = array(); + $this->searchTerms = []; } - function is($value) + public function is($value) { $this->searchTerms['is'] = strval($value); + return $this; } - function toParam() + public function toParam() { return $this->searchTerms; } } +class_alias('Braintree\IsNode', 'Braintree_IsNode'); diff --git a/lib/Braintree/KeyValueNode.php b/lib/Braintree/KeyValueNode.php index ec0cb94..1fd0139 100644 --- a/lib/Braintree/KeyValueNode.php +++ b/lib/Braintree/KeyValueNode.php @@ -1,22 +1,23 @@ name = $name; $this->searchTerm = True; - } - function is($value) + public function is($value) { $this->searchTerm = $value; return $this; } - function toParam() + public function toParam() { return $this->searchTerm; } } +class_alias('Braintree\KeyValueNode', 'Braintree_KeyValueNode'); diff --git a/lib/Braintree/LocalPaymentCompleted.php b/lib/Braintree/LocalPaymentCompleted.php new file mode 100644 index 0000000..07b7360 --- /dev/null +++ b/lib/Braintree/LocalPaymentCompleted.php @@ -0,0 +1,68 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $grantOwnerMerchantId + * @property-read string $grantRecipientMerchantId + * @property-read string $paymentMethodNonce + * @property-read string $token + * @property-read string $updatedFields + */ +class LocalPaymentCompleted extends Base +{ + /** + * factory method: returns an instance of GrantedPaymentInstrumentUpdate + * to the requesting method, with populated properties + * + * @ignore + * @return LocalPaymentCompleted + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $LocalPaymentCompletedAttribs array of localPaymentCompleted data + * @return void + */ + protected function _initialize($localPaymentCompletedAttribs) + { + // set the attributes + $this->_attributes = $localPaymentCompletedAttribs; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } +} +class_alias('Braintree\LocalPaymentCompleted', 'Braintree_LocalPaymentCompleted'); diff --git a/lib/Braintree/MasterpassCard.php b/lib/Braintree/MasterpassCard.php new file mode 100644 index 0000000..aa78c8b --- /dev/null +++ b/lib/Braintree/MasterpassCard.php @@ -0,0 +1,141 @@ +== More information == + * + * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} + * + * @package Braintree + * @category Resources + * + * @property-read string $billingAddress + * @property-read string $bin + * @property-read string $cardType + * @property-read string $cardholderName + * @property-read string $commercial + * @property-read string $countryOfIssuance + * @property-read string $createdAt + * @property-read string $customerId + * @property-read string $customerLocation + * @property-read string $debit + * @property-read string $default + * @property-read string $durbinRegulated + * @property-read string $expirationDate + * @property-read string $expirationMonth + * @property-read string $expirationYear + * @property-read string $expired + * @property-read string $healthcare + * @property-read string $imageUrl + * @property-read string $issuingBank + * @property-read string $last4 + * @property-read string $maskedNumber + * @property-read string $payroll + * @property-read string $prepaid + * @property-read string $productId + * @property-read string $subscriptions + * @property-read string $token + * @property-read string $uniqueNumberIdentifier + * @property-read string $updatedAt + */ +class MasterpassCard extends Base +{ + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * checks whether the card is expired based on the current date + * + * @return boolean + */ + public function isExpired() + { + return $this->expired; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $creditCardAttribs array of creditcard data + * @return void + */ + protected function _initialize($creditCardAttribs) + { + // set the attributes + $this->_attributes = $creditCardAttribs; + + // map each address into its own object + $billingAddress = isset($creditCardAttribs['billingAddress']) ? + Address::factory($creditCardAttribs['billingAddress']) : + null; + + $subscriptionArray = []; + if (isset($creditCardAttribs['subscriptions'])) { + foreach ($creditCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + $this->_set('billingAddress', $billingAddress); + $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); + $this->_set('maskedNumber', $this->bin . '******' . $this->last4); + } + + /** + * returns false if comparing object is not a CreditCard, + * or is a CreditCard with a different id + * + * @param object $otherCreditCard customer to compare against + * @return boolean + */ + public function isEqual($otherMasterpassCard) + { + return !($otherMasterpassCard instanceof self) ? false : $this->token === $otherMasterpassCard->token; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + + /** + * factory method: returns an instance of CreditCard + * to the requesting method, with populated properties + * + * @ignore + * @return MasterpassCard + */ + public static function factory($attributes) + { + $defaultAttributes = [ + 'bin' => '', + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => '', + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } +} +class_alias('Braintree\MasterpassCard', 'Braintree_MasterpassCard'); diff --git a/lib/Braintree/Merchant.php b/lib/Braintree/Merchant.php new file mode 100644 index 0000000..09d8bf4 --- /dev/null +++ b/lib/Braintree/Merchant.php @@ -0,0 +1,36 @@ +_attributes = $attribs; + + $merchantAccountArray = []; + if (isset($attribs['merchantAccounts'])) { + foreach ($attribs['merchantAccounts'] AS $merchantAccount) { + $merchantAccountArray[] = MerchantAccount::factory($merchantAccount); + } + } + $this->_set('merchantAccounts', $merchantAccountArray); + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /** + * returns a string representation of the merchant + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } +} +class_alias('Braintree\Merchant', 'Braintree_Merchant'); diff --git a/lib/Braintree/MerchantAccount.php b/lib/Braintree/MerchantAccount.php index 7c9aaf9..5bde533 100644 --- a/lib/Braintree/MerchantAccount.php +++ b/lib/Braintree/MerchantAccount.php @@ -1,6 +1,7 @@ $attribs)); - } - - public static function find($merchant_account_id) - { - try { - $response = Braintree_Http::get('/merchant_accounts/' . $merchant_account_id); - return self::factory($response['merchantAccount']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound('merchant account with id ' . $merchant_account_id . ' not found'); - } - } - - public static function update($merchant_account_id, $attributes) - { - Braintree_Util::verifyKeys(self::updateSignature(), $attributes); - return self::_doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', array('merchant_account' => $attributes)); - } - - public static function detectSignature($attribs) - { - if (isset($attribs['applicantDetails'])) { - trigger_error("DEPRECATED: Passing applicantDetails to create is deprecated. Please use individual, business, and funding", E_USER_NOTICE); - return self::createDeprecatedSignature(); - } else { - return self::createSignature(); - } - } - - public static function updateSignature() - { - $signature = self::createSignature(); - unset($signature['tosAccepted']); - return $signature; - } - - public static function createSignature() - { - $addressSignature = array('streetAddress', 'postalCode', 'locality', 'region'); - $individualSignature = array( - 'firstName', - 'lastName', - 'email', - 'phone', - 'dateOfBirth', - 'ssn', - array('address' => $addressSignature) - ); - - $businessSignature = array( - 'dbaName', - 'legalName', - 'taxId', - array('address' => $addressSignature) - ); - - $fundingSignature = array( - 'routingNumber', - 'accountNumber', - 'destination', - 'email', - 'mobilePhone' - ); - - return array( - 'id', - 'tosAccepted', - 'masterMerchantAccountId', - array('individual' => $individualSignature), - array('funding' => $fundingSignature), - array('business' => $businessSignature) - ); - } - - public static function createDeprecatedSignature() - { - $applicantDetailsAddressSignature = array('streetAddress', 'postalCode', 'locality', 'region'); - $applicantDetailsSignature = array( - 'companyName', - 'firstName', - 'lastName', - 'email', - 'phone', - 'dateOfBirth', - 'ssn', - 'taxId', - 'routingNumber', - 'accountNumber', - array('address' => $applicantDetailsAddressSignature) - ); - - return array( - array('applicantDetails' => $applicantDetailsSignature), - 'id', - 'tosAccepted', - 'masterMerchantAccountId' - ); - } - - public static function _doCreate($url, $params) - { - $response = Braintree_Http::post($url, $params); - - return self::_verifyGatewayResponse($response); - } - - private static function _doUpdate($url, $params) - { - $response = Braintree_Http::put($url, $params); - - return self::_verifyGatewayResponse($response); - } - - private static function _verifyGatewayResponse($response) - { - if (isset($response['merchantAccount'])) { - // return a populated instance of Braintree_merchantAccount - return new Braintree_Result_Successful( - self::factory($response['merchantAccount']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected merchant account or apiErrorResponse" - ); - } - } - public static function factory($attributes) { $instance = new self(); @@ -155,22 +24,41 @@ protected function _initialize($merchantAccountAttribs) if (isset($merchantAccountAttribs['individual'])) { $individual = $merchantAccountAttribs['individual']; - $this->_set('individualDetails', Braintree_MerchantAccount_IndividualDetails::Factory($individual)); + $this->_set('individualDetails', MerchantAccount\IndividualDetails::Factory($individual)); } if (isset($merchantAccountAttribs['business'])) { $business = $merchantAccountAttribs['business']; - $this->_set('businessDetails', Braintree_MerchantAccount_BusinessDetails::Factory($business)); + $this->_set('businessDetails', MerchantAccount\BusinessDetails::Factory($business)); } if (isset($merchantAccountAttribs['funding'])) { $funding = $merchantAccountAttribs['funding']; - $this->_set('fundingDetails', new Braintree_MerchantAccount_FundingDetails($funding)); + $this->_set('fundingDetails', new MerchantAccount\FundingDetails($funding)); } if (isset($merchantAccountAttribs['masterMerchantAccount'])) { $masterMerchantAccount = $merchantAccountAttribs['masterMerchantAccount']; - $this->_set('masterMerchantAccount', Braintree_MerchantAccount::Factory($masterMerchantAccount)); + $this->_set('masterMerchantAccount', self::Factory($masterMerchantAccount)); } } + + + // static methods redirecting to gateway + + public static function create($attribs) + { + return Configuration::gateway()->merchantAccount()->create($attribs); + } + + public static function find($merchant_account_id) + { + return Configuration::gateway()->merchantAccount()->find($merchant_account_id); + } + + public static function update($merchant_account_id, $attributes) + { + return Configuration::gateway()->merchantAccount()->update($merchant_account_id, $attributes); + } } +class_alias('Braintree\MerchantAccount', 'Braintree_MerchantAccount'); diff --git a/lib/Braintree/MerchantAccount/AddressDetails.php b/lib/Braintree/MerchantAccount/AddressDetails.php index 15349f6..c4caf9a 100644 --- a/lib/Braintree/MerchantAccount/AddressDetails.php +++ b/lib/Braintree/MerchantAccount/AddressDetails.php @@ -1,5 +1,10 @@ _attributes = $businessAttribs; if (isset($businessAttribs['address'])) { - $this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($businessAttribs['address'])); + $this->_set('addressDetails', new AddressDetails($businessAttribs['address'])); } } @@ -17,3 +20,4 @@ public static function factory($attributes) return $instance; } } +class_alias('Braintree\MerchantAccount\BusinessDetails', 'Braintree_MerchantAccount_BusinessDetails'); diff --git a/lib/Braintree/MerchantAccount/FundingDetails.php b/lib/Braintree/MerchantAccount/FundingDetails.php index f33e595..6fac0b5 100644 --- a/lib/Braintree/MerchantAccount/FundingDetails.php +++ b/lib/Braintree/MerchantAccount/FundingDetails.php @@ -1,6 +1,10 @@ _attributes = $individualAttribs; if (isset($individualAttribs['address'])) { - $this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($individualAttribs['address'])); + $this->_set('addressDetails', new AddressDetails($individualAttribs['address'])); } } @@ -17,3 +20,4 @@ public static function factory($attributes) return $instance; } } +class_alias('Braintree\MerchantAccount\IndividualDetails', 'Braintree_MerchantAccount_IndividualDetails'); diff --git a/lib/Braintree/MerchantAccountGateway.php b/lib/Braintree/MerchantAccountGateway.php new file mode 100644 index 0000000..a9704c8 --- /dev/null +++ b/lib/Braintree/MerchantAccountGateway.php @@ -0,0 +1,182 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function create($attribs) + { + Util::verifyKeys(self::detectSignature($attribs), $attribs); + return $this->_doCreate('/merchant_accounts/create_via_api', ['merchant_account' => $attribs]); + } + + public function find($merchant_account_id) + { + try { + $path = $this->_config->merchantPath() . '/merchant_accounts/' . $merchant_account_id; + $response = $this->_http->get($path); + return MerchantAccount::factory($response['merchantAccount']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('merchant account with id ' . $merchant_account_id . ' not found'); + } + } + + public function update($merchant_account_id, $attributes) + { + Util::verifyKeys(self::updateSignature(), $attributes); + return $this->_doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', ['merchant_account' => $attributes]); + } + + public static function detectSignature($attribs) + { + if (isset($attribs['applicantDetails'])) { + trigger_error("DEPRECATED: Passing applicantDetails to create is deprecated. Please use individual, business, and funding", E_USER_NOTICE); + return self::createDeprecatedSignature(); + } else { + return self::createSignature(); + } + } + + public static function updateSignature() + { + $signature = self::createSignature(); + unset($signature['tosAccepted']); + return $signature; + } + + public function createForCurrency($attribs) + { + $response = $this->_http->post($this->_config->merchantPath() . '/merchant_accounts/create_for_currency', ['merchant_account' => $attribs]); + return $this->_verifyGatewayResponse($response); + } + + public function all() + { + $pager = [ + 'object' => $this, + 'method' => 'fetchMerchantAccounts', + ]; + return new PaginatedCollection($pager); + } + + public function fetchMerchantAccounts($page) + { + $response = $this->_http->get($this->_config->merchantPath() . '/merchant_accounts?page=' . $page); + $body = $response['merchantAccounts']; + $merchantAccounts = Util::extractattributeasarray($body, 'merchantAccount'); + $totalItems = $body['totalItems'][0]; + $pageSize = $body['pageSize'][0]; + return new PaginatedResult($totalItems, $pageSize, $merchantAccounts); + } + + public static function createSignature() + { + $addressSignature = ['streetAddress', 'postalCode', 'locality', 'region']; + $individualSignature = [ + 'firstName', + 'lastName', + 'email', + 'phone', + 'dateOfBirth', + 'ssn', + ['address' => $addressSignature] + ]; + + $businessSignature = [ + 'dbaName', + 'legalName', + 'taxId', + ['address' => $addressSignature] + ]; + + $fundingSignature = [ + 'routingNumber', + 'accountNumber', + 'destination', + 'email', + 'mobilePhone', + 'descriptor', + ]; + + return [ + 'id', + 'tosAccepted', + 'masterMerchantAccountId', + ['individual' => $individualSignature], + ['funding' => $fundingSignature], + ['business' => $businessSignature] + ]; + } + + public static function createDeprecatedSignature() + { + $applicantDetailsAddressSignature = ['streetAddress', 'postalCode', 'locality', 'region']; + $applicantDetailsSignature = [ + 'companyName', + 'firstName', + 'lastName', + 'email', + 'phone', + 'dateOfBirth', + 'ssn', + 'taxId', + 'routingNumber', + 'accountNumber', + ['address' => $applicantDetailsAddressSignature] + ]; + + return [ + ['applicantDetails' => $applicantDetailsSignature], + 'id', + 'tosAccepted', + 'masterMerchantAccountId' + ]; + } + + public function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + private function _doUpdate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->put($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + private function _verifyGatewayResponse($response) + { + if (isset($response['response'])) { + $response = $response['response']; + } + if (isset($response['merchantAccount'])) { + // return a populated instance of merchantAccount + return new Result\Successful( + MerchantAccount::factory($response['merchantAccount']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected merchant account or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\MerchantAccountGateway', 'Braintree_MerchantAccountGateway'); diff --git a/lib/Braintree/MerchantGateway.php b/lib/Braintree/MerchantGateway.php new file mode 100644 index 0000000..d628e88 --- /dev/null +++ b/lib/Braintree/MerchantGateway.php @@ -0,0 +1,42 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasClientCredentials(); + $this->_http = new Http($gateway->config); + $this->_http->useClientCredentials(); + } + + public function create($attribs) + { + $response = $this->_http->post('/merchants/create_via_api', ['merchant' => $attribs]); + return $this->_verifyGatewayResponse($response); + } + + private function _verifyGatewayResponse($response) + { + if (isset($response['response']['merchant'])) { + // return a populated instance of merchant + return new Result\Successful([ + Merchant::factory($response['response']['merchant']), + OAuthCredentials::factory($response['response']['credentials']), + ]); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected merchant or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\MerchantGateway', 'Braintree_MerchantGateway'); diff --git a/lib/Braintree/Modification.php b/lib/Braintree/Modification.php index 7563b57..e1d32b2 100644 --- a/lib/Braintree/Modification.php +++ b/lib/Braintree/Modification.php @@ -1,17 +1,11 @@ _attributes = $attributes; - - $addOnArray = array(); - if (isset($attributes['addOns'])) { - foreach ($attributes['addOns'] AS $addOn) { - $addOnArray[] = Braintree_addOn::factory($addOn); - } - } - $this->_attributes['addOns'] = $addOnArray; } public static function factory($attributes) @@ -20,4 +14,9 @@ public static function factory($attributes) $instance->_initialize($attributes); return $instance; } + + public function __toString() { + return get_called_class() . '[' . Util::attributesToString($this->_attributes) . ']'; + } } +class_alias('Braintree\Modification', 'Braintree_Modification'); diff --git a/lib/Braintree/MultipleValueNode.php b/lib/Braintree/MultipleValueNode.php index 3100e4d..397c610 100644 --- a/lib/Braintree/MultipleValueNode.php +++ b/lib/Braintree/MultipleValueNode.php @@ -1,15 +1,18 @@ name = $name; - $this->items = array(); + $this->items = []; $this->allowedValues = $allowedValues; } - function in($values) + public function in($values) { $bad_values = array_diff($values, $this->allowedValues); if (count($this->allowedValues) > 0 && count($bad_values) > 0) { @@ -25,13 +28,14 @@ function in($values) return $this; } - function is($value) + public function is($value) { - return $this->in(array($value)); + return $this->in([$value]); } - function toParam() + public function toParam() { return $this->items; } } +class_alias('Braintree\MultipleValueNode', 'Braintree_MultipleValueNode'); diff --git a/lib/Braintree/MultipleValueOrTextNode.php b/lib/Braintree/MultipleValueOrTextNode.php index e0faca4..c98ee95 100644 --- a/lib/Braintree/MultipleValueOrTextNode.php +++ b/lib/Braintree/MultipleValueOrTextNode.php @@ -1,45 +1,47 @@ textNode = new Braintree_TextNode($name); + $this->textNode = new TextNode($name); } - function contains($value) + public function contains($value) { $this->textNode->contains($value); return $this; } - function endsWith($value) + public function endsWith($value) { $this->textNode->endsWith($value); return $this; } - function is($value) + public function is($value) { $this->textNode->is($value); return $this; } - function isNot($value) + public function isNot($value) { $this->textNode->isNot($value); return $this; } - function startsWith($value) + public function startsWith($value) { $this->textNode->startsWith($value); return $this; } - function toParam() + public function toParam() { return array_merge(parent::toParam(), $this->textNode->toParam()); } } +class_alias('Braintree\MultipleValueOrTextNode', 'Braintree_MultipleValueOrTextNode'); diff --git a/lib/Braintree/OAuthAccessRevocation.php b/lib/Braintree/OAuthAccessRevocation.php new file mode 100644 index 0000000..62a2897 --- /dev/null +++ b/lib/Braintree/OAuthAccessRevocation.php @@ -0,0 +1,32 @@ +_initialize($attributes); + + return $instance; + } + + /** + * @ignore + */ + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } +} +class_alias('Braintree\OAuthAccessRevocation', 'Braintree_OAuthAccessRevocation'); diff --git a/lib/Braintree/OAuthCredentials.php b/lib/Braintree/OAuthCredentials.php new file mode 100644 index 0000000..60de5fb --- /dev/null +++ b/lib/Braintree/OAuthCredentials.php @@ -0,0 +1,34 @@ +_attributes = $attribs; + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /** + * returns a string representation of the access token + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } +} +class_alias('Braintree\OAuthCredentials', 'Braintree_OAuthCredentials'); diff --git a/lib/Braintree/OAuthGateway.php b/lib/Braintree/OAuthGateway.php new file mode 100644 index 0000000..4e2d1b2 --- /dev/null +++ b/lib/Braintree/OAuthGateway.php @@ -0,0 +1,124 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_http = new Http($gateway->config); + $this->_http->useClientCredentials(); + + $this->_config->assertHasClientCredentials(); + } + + public function createTokenFromCode($params) + { + $params['grantType'] = "authorization_code"; + return $this->_createToken($params); + } + + public function createTokenFromRefreshToken($params) + { + $params['grantType'] = "refresh_token"; + return $this->_createToken($params); + } + + public function revokeAccessToken($accessToken) + { + $params = ['token' => $accessToken]; + $response = $this->_http->post('/oauth/revoke_access_token', $params); + return $this->_verifyGatewayResponse($response); + } + + private function _createToken($params) + { + $params = ['credentials' => $params]; + $response = $this->_http->post('/oauth/access_tokens', $params); + return $this->_verifyGatewayResponse($response); + } + + private function _verifyGatewayResponse($response) + { + if (isset($response['credentials'])) { + $result = new Result\Successful( + OAuthCredentials::factory($response['credentials']) + ); + return $this->_mapSuccess($result); + } else if (isset($response['result'])) { + $result = new Result\Successful( + OAuthResult::factory($response['result']) + ); + return $this->_mapAccessTokenRevokeSuccess($result); + } else if (isset($response['apiErrorResponse'])) { + $result = new Result\Error($response['apiErrorResponse']); + return $this->_mapError($result); + } else { + throw new Exception\Unexpected( + "Expected credentials or apiErrorResponse" + ); + } + } + + public function _mapError($result) + { + $error = $result->errors->deepAll()[0]; + + if ($error->code == Error\Codes::OAUTH_INVALID_GRANT) { + $result->error = 'invalid_grant'; + } else if ($error->code == Error\Codes::OAUTH_INVALID_CREDENTIALS) { + $result->error = 'invalid_credentials'; + } else if ($error->code == Error\Codes::OAUTH_INVALID_SCOPE) { + $result->error = 'invalid_scope'; + } + $result->errorDescription = explode(': ', $error->message)[1]; + return $result; + } + + public function _mapAccessTokenRevokeSuccess($result) + { + $result->revocationResult = $result->success; + return $result; + } + + public function _mapSuccess($result) + { + $credentials = $result->credentials; + $result->accessToken = $credentials->accessToken; + $result->refreshToken = $credentials->refreshToken; + $result->tokenType = $credentials->tokenType; + $result->expiresAt = $credentials->expiresAt; + return $result; + } + + public function connectUrl($params = []) + { + $query = Util::camelCaseToDelimiterArray($params, '_'); + $query['client_id'] = $this->_config->getClientId(); + $queryString = preg_replace('/\%5B\d+\%5D/', '%5B%5D', http_build_query($query)); + + return $this->_config->baseUrl() . '/oauth/connect?' . $queryString; + } + + /** + * @deprecated since version 3.26.1 + */ + public function computeSignature($url) + { + $key = hash('sha256', $this->_config->getClientSecret(), true); + return hash_hmac('sha256', $url, $key); + } +} +class_alias('Braintree\OAuthGateway', 'Braintree_OAuthGateway'); diff --git a/lib/Braintree/OAuthResult.php b/lib/Braintree/OAuthResult.php new file mode 100644 index 0000000..9c3e4e6 --- /dev/null +++ b/lib/Braintree/OAuthResult.php @@ -0,0 +1,34 @@ +_attributes = $attribs; + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /** + * returns a string representation of the result + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } +} +class_alias('Braintree\OAuthResult', 'Braintree_OAuthResult'); diff --git a/lib/Braintree/PaginatedCollection.php b/lib/Braintree/PaginatedCollection.php new file mode 100644 index 0000000..9deef04 --- /dev/null +++ b/lib/Braintree/PaginatedCollection.php @@ -0,0 +1,120 @@ + + * $result = MerchantAccount::all(); + * + * foreach($result as $merchantAccount) { + * print_r($merchantAccount->status); + * } + * + * + * @package Braintree + * @subpackage Utility + */ +class PaginatedCollection implements Iterator +{ + private $_pager; + private $_pageSize; + private $_currentPage; + private $_index; + private $_totalItems; + private $_items; + + /** + * set up the paginated collection + * + * expects an array of an object and method to call on it + * + * @param array $pager + */ + public function __construct($pager) + { + $this->_pager = $pager; + $this->_pageSize = 0; + $this->_currentPage = 0; + $this->_totalItems = 0; + $this->_index = 0; + } + + /** + * returns the current item when iterating with foreach + */ + public function current() + { + return $this->_items[($this->_index % $this->_pageSize)]; + } + + public function key() + { + return null; + } + + /** + * advances to the next item in the collection when iterating with foreach + */ + public function next() + { + ++$this->_index; + } + + /** + * rewinds the collection to the first item when iterating with foreach + */ + public function rewind() + { + $this->_index = 0; + $this->_currentPage = 0; + $this->_pageSize = 0; + $this->_totalItems = 0; + $this->_items = []; + } + + /** + * returns whether the current item is valid when iterating with foreach + */ + public function valid() + { + if ($this->_currentPage == 0 || $this->_index % $this->_pageSize == 0 && $this->_index < $this->_totalItems) + { + $this->_getNextPage(); + } + + return $this->_index < $this->_totalItems; + } + + private function _getNextPage() + { + $this->_currentPage++; + $object = $this->_pager['object']; + $method = $this->_pager['method']; + + if (isset($this->_pager['query'])) { + $query = $this->_pager['query']; + $result = call_user_func( + [$object, $method], + $query, + $this->_currentPage + ); + } else { + $result = call_user_func( + [$object, $method], + $this->_currentPage + ); + } + + $this->_totalItems= $result->getTotalItems(); + $this->_pageSize = $result->getPageSize(); + $this->_items = $result->getCurrentPage(); + } +} +class_alias('Braintree\PaginatedCollection', 'Braintree_PaginatedCollection'); diff --git a/lib/Braintree/PaginatedResult.php b/lib/Braintree/PaginatedResult.php new file mode 100644 index 0000000..9b383ab --- /dev/null +++ b/lib/Braintree/PaginatedResult.php @@ -0,0 +1,32 @@ +_totalItems = $totalItems; + $this->_pageSize = $pageSize; + $this->_currentPage = $currentPage; + } + + public function getTotalItems() + { + return $this->_totalItems; + } + + public function getPageSize() + { + return $this->_pageSize; + } + + public function getCurrentPage() + { + return $this->_currentPage; + } +} +class_alias('Braintree\PaginatedResult', 'Braintree_PaginatedResult'); diff --git a/lib/Braintree/PartialMatchNode.php b/lib/Braintree/PartialMatchNode.php index 076204a..5d8dc91 100644 --- a/lib/Braintree/PartialMatchNode.php +++ b/lib/Braintree/PartialMatchNode.php @@ -1,16 +1,18 @@ searchTerms["starts_with"] = strval($value); return $this; } - function endsWith($value) + public function endsWith($value) { $this->searchTerms["ends_with"] = strval($value); return $this; } } +class_alias('Braintree\PartialMatchNode', 'Braintree_PartialMatchNode'); diff --git a/lib/Braintree/PartnerMerchant.php b/lib/Braintree/PartnerMerchant.php index 48673e7..d5ac152 100644 --- a/lib/Braintree/PartnerMerchant.php +++ b/lib/Braintree/PartnerMerchant.php @@ -1,29 +1,23 @@ _attributes = $attributes; } } +class_alias('Braintree\PartnerMerchant', 'Braintree_PartnerMerchant'); diff --git a/lib/Braintree/PayPalAccount.php b/lib/Braintree/PayPalAccount.php new file mode 100644 index 0000000..15e334e --- /dev/null +++ b/lib/Braintree/PayPalAccount.php @@ -0,0 +1,109 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $customerId + * @property-read string $email + * @property-read string $token + * @property-read string $imageUrl + */ +class PayPalAccount extends Base +{ + /** + * factory method: returns an instance of PayPalAccount + * to the requesting method, with populated properties + * + * @ignore + * @return PayPalAccount + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $paypalAccountAttribs array of paypalAccount data + * @return void + */ + protected function _initialize($paypalAccountAttribs) + { + // set the attributes + $this->_attributes = $paypalAccountAttribs; + + $subscriptionArray = []; + if (isset($paypalAccountAttribs['subscriptions'])) { + foreach ($paypalAccountAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } + + + // static methods redirecting to gateway + + public static function find($token) + { + return Configuration::gateway()->payPalAccount()->find($token); + } + + public static function update($token, $attributes) + { + return Configuration::gateway()->payPalAccount()->update($token, $attributes); + } + + public static function delete($token) + { + return Configuration::gateway()->payPalAccount()->delete($token); + } + + public static function sale($token, $transactionAttribs) + { + return Configuration::gateway()->payPalAccount()->sale($token, $transactionAttribs); + } +} +class_alias('Braintree\PayPalAccount', 'Braintree_PayPalAccount'); diff --git a/lib/Braintree/PayPalAccountGateway.php b/lib/Braintree/PayPalAccountGateway.php new file mode 100644 index 0000000..9302a17 --- /dev/null +++ b/lib/Braintree/PayPalAccountGateway.php @@ -0,0 +1,178 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class PayPalAccountGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + + /** + * find a paypalAccount by token + * + * @access public + * @param string $token paypal accountunique id + * @return PayPalAccount + * @throws Exception\NotFound + */ + public function find($token) + { + $this->_validateId($token); + try { + $path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token; + $response = $this->_http->get($path); + return PayPalAccount::factory($response['paypalAccount']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'paypal account with token ' . $token . ' not found' + ); + } + + } + + /** + * updates the paypalAccount record + * + * if calling this method in context, $token + * is the 2nd attribute. $token is not sent in object context. + * + * @access public + * @param array $attributes + * @param string $token (optional) + * @return Result\Successful or Result\Error + */ + public function update($token, $attributes) + { + Util::verifyKeys(self::updateSignature(), $attributes); + $this->_validateId($token); + return $this->_doUpdate('put', '/payment_methods/paypal_account/' . $token, ['paypalAccount' => $attributes]); + } + + public function delete($token) + { + $this->_validateId($token); + $path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token; + $this->_http->delete($path); + return new Result\Successful(); + } + + /** + * create a new sale for the current PayPal account + * + * @param string $token + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + * @see Transaction::sale() + */ + public function sale($token, $transactionAttribs) + { + $this->_validateId($token); + return Transaction::sale( + array_merge( + $transactionAttribs, + ['paymentMethodToken' => $token] + ) + ); + } + + public static function updateSignature() + { + return [ + 'token', + ['options' => ['makeDefault']] + ]; + } + + /** + * sends the update request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + private function _doUpdate($httpVerb, $subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->$httpVerb($fullPath, $params); + return $this->_verifyGatewayResponse($response); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new PayPalAccount object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['paypalAccount'])) { + // return a populated instance of PayPalAccount + return new Result\Successful( + PayPalAccount::factory($response['paypalAccount']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + 'Expected paypal account or apiErrorResponse' + ); + } + } + + /** + * verifies that a valid paypal account identifier is being used + * @ignore + * @param string $identifier + * @param Optional $string $identifierType type of identifier supplied, default 'token' + * @throws InvalidArgumentException + */ + private function _validateId($identifier = null, $identifierType = 'token') + { + if (empty($identifier)) { + throw new InvalidArgumentException( + 'expected paypal account id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { + throw new InvalidArgumentException( + $identifier . ' is an invalid paypal account ' . $identifierType . '.' + ); + } + } +} +class_alias('Braintree\PayPalAccountGateway', 'Braintree_PayPalAccountGateway'); diff --git a/lib/Braintree/PaymentInstrumentType.php b/lib/Braintree/PaymentInstrumentType.php new file mode 100644 index 0000000..8218e42 --- /dev/null +++ b/lib/Braintree/PaymentInstrumentType.php @@ -0,0 +1,19 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class PaymentMethod extends Base +{ + // static methods redirecting to gateway + + public static function create($attribs) + { + return Configuration::gateway()->paymentMethod()->create($attribs); + } + + public static function find($token) + { + return Configuration::gateway()->paymentMethod()->find($token); + } + + public static function update($token, $attribs) + { + return Configuration::gateway()->paymentMethod()->update($token, $attribs); + } + + public static function delete($token, $options=[]) + { + return Configuration::gateway()->paymentMethod()->delete($token, $options); + } +} +class_alias('Braintree\PaymentMethod', 'Braintree_PaymentMethod'); diff --git a/lib/Braintree/PaymentMethodGateway.php b/lib/Braintree/PaymentMethodGateway.php new file mode 100644 index 0000000..66630f5 --- /dev/null +++ b/lib/Braintree/PaymentMethodGateway.php @@ -0,0 +1,363 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class PaymentMethodGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + + public function create($attribs) + { + Util::verifyKeys(self::createSignature(), $attribs); + return $this->_doCreate('/payment_methods', ['payment_method' => $attribs]); + } + + /** + * find a PaymentMethod by token + * + * @param string $token payment method unique id + * @return CreditCard|PayPalAccount + * @throws Exception\NotFound + */ + public function find($token) + { + $this->_validateId($token); + try { + $path = $this->_config->merchantPath() . '/payment_methods/any/' . $token; + $response = $this->_http->get($path); + if (isset($response['creditCard'])) { + return CreditCard::factory($response['creditCard']); + } else if (isset($response['paypalAccount'])) { + return PayPalAccount::factory($response['paypalAccount']); + } else if (isset($response['coinbaseAccount'])) { + return CoinbaseAccount::factory($response['coinbaseAccount']); + } else if (isset($response['applePayCard'])) { + return ApplePayCard::factory($response['applePayCard']); + } else if (isset($response['androidPayCard'])) { + return AndroidPayCard::factory($response['androidPayCard']); + } else if (isset($response['amexExpressCheckoutCard'])) { + return AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']); + } else if (isset($response['europeBankAccount'])) { + return EuropeBankAccount::factory($response['europeBankAccount']); + } else if (isset($response['usBankAccount'])) { + return UsBankAccount::factory($response['usBankAccount']); + } else if (isset($response['venmoAccount'])) { + return VenmoAccount::factory($response['venmoAccount']); + } else if (isset($response['visaCheckoutCard'])) { + return VisaCheckoutCard::factory($response['visaCheckoutCard']); + } else if (isset($response['masterpassCard'])) { + return MasterpassCard::factory($response['masterpassCard']); + } else if (isset($response['samsungPayCard'])) { + return SamsungPayCard::factory($response['samsungPayCard']); + } else if (is_array($response)) { + return UnknownPaymentMethod::factory($response); + } + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'payment method with token ' . $token . ' not found' + ); + } + } + + public function update($token, $attribs) + { + Util::verifyKeys(self::updateSignature(), $attribs); + return $this->_doUpdate('/payment_methods/any/' . $token, ['payment_method' => $attribs]); + } + + public function delete($token, $options=[]) + { + Util::verifyKeys(self::deleteSignature(), $options); + $this->_validateId($token); + $queryString = ""; + if (!empty($options)) { + $queryString = "?" . http_build_query(Util::camelCaseToDelimiterArray($options, '_')); + } + return $this->_doDelete('/payment_methods/any/' . $token . $queryString); + } + + public function grant($sharedPaymentMethodToken, $attribs=[]) + { + if (is_bool($attribs) === true) { + $attribs = ['allow_vaulting' => $attribs]; + } + $options = [ 'shared_payment_method_token' => $sharedPaymentMethodToken ]; + + return $this->_doCreate( + '/payment_methods/grant', + [ + 'payment_method' => array_merge($attribs, $options) + ] + ); + } + + public function revoke($sharedPaymentMethodToken) + { + return $this->_doCreate( + '/payment_methods/revoke', + [ + 'payment_method' => [ + 'shared_payment_method_token' => $sharedPaymentMethodToken + ] + ] + ); + } + + private static function baseSignature() + { + $billingAddressSignature = AddressGateway::createSignature(); + $optionsSignature = [ + 'failOnDuplicatePaymentMethod', + 'makeDefault', + 'verificationMerchantAccountId', + 'verifyCard', + 'verificationAmount', + 'usBankAccountVerificationMethod', + ['paypal' => [ + 'payee_email', + 'payeeEmail', + 'order_id', + 'orderId', + 'custom_field', + 'customField', + 'description', + 'amount', + ['shipping' => + [ + 'firstName', 'lastName', 'company', 'countryName', + 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'extendedAddress', 'locality', 'postalCode', 'region', + 'streetAddress'], + ], + ]], + ]; + return [ + 'billingAddressId', + 'cardholderName', + 'cvv', + 'deviceData', + 'expirationDate', + 'expirationMonth', + 'expirationYear', + 'number', + 'paymentMethodNonce', + 'token', + ['options' => $optionsSignature], + ['billingAddress' => $billingAddressSignature] + ]; + } + + public static function createSignature() + { + $signature = array_merge(self::baseSignature(), ['customerId', 'paypalRefreshToken', 'paypalVaultWithoutUpgrade']); + return $signature; + } + + public static function updateSignature() + { + $billingAddressSignature = AddressGateway::updateSignature(); + array_push($billingAddressSignature, [ + 'options' => [ + 'updateExisting' + ] + ]); + $signature = array_merge(self::baseSignature(), [ + 'deviceSessionId', + 'venmoSdkPaymentMethodCode', + 'fraudMerchantId', + ['billingAddress' => $billingAddressSignature] + ]); + return $signature; + } + + private static function deleteSignature() + { + return ['revokeAllGrants']; + } + + /** + * sends the create request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + public function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * sends the update request to the gateway + * + * @ignore + * @param string $subPath + * @param array $params + * @return mixed + */ + public function _doUpdate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->put($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + + /** + * sends the delete request to the gateway + * + * @ignore + * @param string $subPath + * @return mixed + */ + public function _doDelete($subPath) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $this->_http->delete($fullPath); + return new Result\Successful(); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new CreditCard or PayPalAccount object + * and encapsulates it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['creditCard'])) { + return new Result\Successful( + CreditCard::factory($response['creditCard']), + 'paymentMethod' + ); + } else if (isset($response['paypalAccount'])) { + return new Result\Successful( + PayPalAccount::factory($response['paypalAccount']), + "paymentMethod" + ); + } else if (isset($response['coinbaseAccount'])) { + return new Result\Successful( + CoinbaseAccount::factory($response['coinbaseAccount']), + "paymentMethod" + ); + } else if (isset($response['applePayCard'])) { + return new Result\Successful( + ApplePayCard::factory($response['applePayCard']), + "paymentMethod" + ); + } else if (isset($response['androidPayCard'])) { + return new Result\Successful( + AndroidPayCard::factory($response['androidPayCard']), + "paymentMethod" + ); + } else if (isset($response['amexExpressCheckoutCard'])) { + return new Result\Successful( + AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']), + "paymentMethod" + ); + } else if (isset($response['usBankAccount'])) { + return new Result\Successful( + UsBankAccount::factory($response['usBankAccount']), + "paymentMethod" + ); + } else if (isset($response['venmoAccount'])) { + return new Result\Successful( + VenmoAccount::factory($response['venmoAccount']), + "paymentMethod" + ); + } else if (isset($response['visaCheckoutCard'])) { + return new Result\Successful( + VisaCheckoutCard::factory($response['visaCheckoutCard']), + "paymentMethod" + ); + } else if (isset($response['masterpassCard'])) { + return new Result\Successful( + MasterpassCard::factory($response['masterpassCard']), + "paymentMethod" + ); + } else if (isset($response['samsungPayCard'])) { + return new Result\Successful( + MasterpassCard::factory($response['samsungPayCard']), + "paymentMethod" + ); + } else if (isset($response['paymentMethodNonce'])) { + return new Result\Successful( + PaymentMethodNonce::factory($response['paymentMethodNonce']), + "paymentMethodNonce" + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else if (is_array($response)) { + return new Result\Successful( + UnknownPaymentMethod::factory($response), + "paymentMethod" + ); + } else { + throw new Exception\Unexpected( + 'Expected payment method or apiErrorResponse' + ); + } + } + + /** + * verifies that a valid payment method identifier is being used + * @ignore + * @param string $identifier + * @param Optional $string $identifierType type of identifier supplied, default 'token' + * @throws InvalidArgumentException + */ + private function _validateId($identifier = null, $identifierType = 'token') + { + if (empty($identifier)) { + throw new InvalidArgumentException( + 'expected payment method id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { + throw new InvalidArgumentException( + $identifier . ' is an invalid payment method ' . $identifierType . '.' + ); + } + } +} +class_alias('Braintree\PaymentMethodGateway', 'Braintree_PaymentMethodGateway'); diff --git a/lib/Braintree/PaymentMethodNonce.php b/lib/Braintree/PaymentMethodNonce.php new file mode 100644 index 0000000..e125e21 --- /dev/null +++ b/lib/Braintree/PaymentMethodNonce.php @@ -0,0 +1,56 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class PaymentMethodNonce extends Base +{ + // static methods redirecting to gateway + + public static function create($token) + { + return Configuration::gateway()->paymentMethodNonce()->create($token); + } + + public static function find($nonce) + { + return Configuration::gateway()->paymentMethodNonce()->find($nonce); + } + + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + protected function _initialize($nonceAttributes) + { + $this->_attributes = $nonceAttributes; + $this->_set('nonce', $nonceAttributes['nonce']); + $this->_set('type', $nonceAttributes['type']); + + if(isset($nonceAttributes['threeDSecureInfo'])) { + $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($nonceAttributes['threeDSecureInfo'])); + } + + if(isset($nonceAttributes['binData'])) { + $this->_set('binData', BinData::factory($nonceAttributes['binData'])); + } + } +} +class_alias('Braintree\PaymentMethodNonce', 'Braintree_PaymentMethodNonce'); diff --git a/lib/Braintree/PaymentMethodNonceGateway.php b/lib/Braintree/PaymentMethodNonceGateway.php new file mode 100644 index 0000000..40ad8af --- /dev/null +++ b/lib/Braintree/PaymentMethodNonceGateway.php @@ -0,0 +1,64 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class PaymentMethodNonceGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_http = new Http($gateway->config); + } + + + public function create($token) + { + $subPath = '/payment_methods/' . $token . '/nonces'; + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath); + + return new Result\Successful( + PaymentMethodNonce::factory($response['paymentMethodNonce']), + "paymentMethodNonce" + ); + } + + /** + * @access public + * + */ + public function find($nonce) + { + try { + $path = $this->_config->merchantPath() . '/payment_method_nonces/' . $nonce; + $response = $this->_http->get($path); + return PaymentMethodNonce::factory($response['paymentMethodNonce']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'payment method nonce with id ' . $nonce . ' not found' + ); + } + + } +} +class_alias('Braintree\PaymentMethodNonceGateway', 'Braintree_PaymentMethodNonceGateway'); diff --git a/lib/Braintree/Plan.php b/lib/Braintree/Plan.php index b0fb3d0..a92c604 100644 --- a/lib/Braintree/Plan.php +++ b/lib/Braintree/Plan.php @@ -1,21 +1,8 @@ $response['plans']); - } else { - $plans = array("plan" => array()); - } - - return Braintree_Util::extractAttributeAsArray( - $plans, - 'plan' - ); - } +namespace Braintree; +class Plan extends Base +{ public static function factory($attributes) { $instance = new self(); @@ -28,28 +15,37 @@ protected function _initialize($attributes) { $this->_attributes = $attributes; - $addOnArray = array(); + $addOnArray = []; if (isset($attributes['addOns'])) { foreach ($attributes['addOns'] AS $addOn) { - $addOnArray[] = Braintree_AddOn::factory($addOn); + $addOnArray[] = AddOn::factory($addOn); } } $this->_attributes['addOns'] = $addOnArray; - $discountArray = array(); + $discountArray = []; if (isset($attributes['discounts'])) { foreach ($attributes['discounts'] AS $discount) { - $discountArray[] = Braintree_Discount::factory($discount); + $discountArray[] = Discount::factory($discount); } } $this->_attributes['discounts'] = $discountArray; - $planArray = array(); + $planArray = []; if (isset($attributes['plans'])) { foreach ($attributes['plans'] AS $plan) { - $planArray[] = Braintree_Plan::factory($plan); + $planArray[] = self::factory($plan); } } $this->_attributes['plans'] = $planArray; } + + + // static methods redirecting to gateway + + public static function all() + { + return Configuration::gateway()->plan()->all(); + } } +class_alias('Braintree\Plan', 'Braintree_Plan'); diff --git a/lib/Braintree/PlanGateway.php b/lib/Braintree/PlanGateway.php new file mode 100644 index 0000000..22beaee --- /dev/null +++ b/lib/Braintree/PlanGateway.php @@ -0,0 +1,34 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function all() + { + $path = $this->_config->merchantPath() . '/plans'; + $response = $this->_http->get($path); + if (key_exists('plans', $response)){ + $plans = ["plan" => $response['plans']]; + } else { + $plans = ["plan" => []]; + } + + return Util::extractAttributeAsArray( + $plans, + 'plan' + ); + } +} +class_alias('Braintree\PlanGateway', 'Braintree_PlanGateway'); diff --git a/lib/Braintree/RangeNode.php b/lib/Braintree/RangeNode.php index fdc4307..622939a 100644 --- a/lib/Braintree/RangeNode.php +++ b/lib/Braintree/RangeNode.php @@ -1,38 +1,40 @@ name = $name; - $this->searchTerms = array(); + $this->searchTerms = []; } - function greaterThanOrEqualTo($value) + public function greaterThanOrEqualTo($value) { $this->searchTerms['min'] = $value; return $this; } - function lessThanOrEqualTo($value) + public function lessThanOrEqualTo($value) { $this->searchTerms['max'] = $value; return $this; } - function is($value) + public function is($value) { $this->searchTerms['is'] = $value; return $this; } - function between($min, $max) + public function between($min, $max) { return $this->greaterThanOrEqualTo($min)->lessThanOrEqualTo($max); } - function toParam() + public function toParam() { return $this->searchTerms; } } +class_alias('Braintree\RangeNode', 'Braintree_RangeNode'); diff --git a/lib/Braintree/ResourceCollection.php b/lib/Braintree/ResourceCollection.php index dc09cf1..2a5dd4d 100644 --- a/lib/Braintree/ResourceCollection.php +++ b/lib/Braintree/ResourceCollection.php @@ -1,20 +1,17 @@ - * $result = Braintree_Customer::all(); + * $result = Customer::all(); * * foreach($result as $transaction) { * print_r($transaction->id); @@ -23,12 +20,12 @@ * * @package Braintree * @subpackage Utility - * @copyright 2010 Braintree Payment Solutions */ -class Braintree_ResourceCollection implements Iterator +class ResourceCollection implements Iterator { - private $_index; private $_batchIndex; + private $_ids; + private $_index; private $_items; private $_pageSize; private $_pager; @@ -38,8 +35,8 @@ class Braintree_ResourceCollection implements Iterator * * expects an array of attributes with literal keys * - * @param array $attributes - * @param array $pagerAttribs + * @param array $response + * @param array $pager */ public function __construct($response, $pager) { @@ -64,7 +61,7 @@ public function current() public function firstItem() { $ids = $this->_ids; - $page = $this->_getPage(array($ids[0])); + $page = $this->_getPage([$ids[0]]); return $page[0]; } @@ -82,7 +79,7 @@ public function next() } /** - * rewinds thtestIterateOverResultse collection to the first item when iterating with foreach + * rewinds the testIterateOverResults collection to the first item when iterating with foreach */ public function rewind() { @@ -115,7 +112,7 @@ private function _getNextPage() { if (empty($this->_ids)) { - $this->_items = array(); + $this->_items = []; } else { @@ -128,21 +125,32 @@ private function _getNextPage() /** * requests the next page of results for the collection * - * @return none + * @return void */ private function _getPage($ids) { - $className = $this->_pager['className']; - $classMethod = $this->_pager['classMethod']; - $methodArgs = array(); + $object = $this->_pager['object']; + $method = $this->_pager['method']; + $methodArgs = []; foreach ($this->_pager['methodArgs'] as $arg) { array_push($methodArgs, $arg); } array_push($methodArgs, $ids); return call_user_func_array( - array($className, $classMethod), + [$object, $method], $methodArgs ); } + + /** + * returns all IDs in the collection + * + * @return array + */ + public function getIds() + { + return $this->_ids; + } } +class_alias('Braintree\ResourceCollection', 'Braintree_ResourceCollection'); diff --git a/lib/Braintree/Result/CreditCardVerification.php b/lib/Braintree/Result/CreditCardVerification.php index 68bc75a..c325755 100644 --- a/lib/Braintree/Result/CreditCardVerification.php +++ b/lib/Braintree/Result/CreditCardVerification.php @@ -1,11 +1,8 @@ _initializeFromArray($attributes); } + /** * initializes instance properties from the keys/values of an array * @ignore * @access protected * @param $aAttribs array of properties to set - single level - * @return none + * @return void */ private function _initializeFromArray($attributes) { + if(isset($attributes['riskData'])) + { + $attributes['riskData'] = RiskData::factory($attributes['riskData']); + } + $this->_attributes = $attributes; foreach($attributes AS $name => $value) { $varName = "_$name"; $this->$varName = $value; - // $this->$varName = Braintree_Util::delimiterToCamelCase($value, '_'); } } + /** - * * @ignore */ public function __get($name) @@ -81,6 +84,17 @@ public function __get($name) public function __toString() { return __CLASS__ . '[' . - Braintree_Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; + } + + public static function allStatuses() + { + return [ + CreditCardVerification::FAILED, + CreditCardVerification::GATEWAY_REJECTED, + CreditCardVerification::PROCESSOR_DECLINED, + CreditCardVerification::VERIFIED + ]; } } +class_alias('Braintree\Result\CreditCardVerification', 'Braintree_Result_CreditCardVerification'); diff --git a/lib/Braintree/Result/Error.php b/lib/Braintree/Result/Error.php index 94f6bce..c0d8ba7 100644 --- a/lib/Braintree/Result/Error.php +++ b/lib/Braintree/Result/Error.php @@ -1,11 +1,12 @@ - * $result = Braintree_Transaction::void('abc123'); + * $result = Transaction::void('abc123'); * if ($result->success) { * // Successful Result * } else { - * // Braintree_Result_Error + * // Result\Error * } * * * @package Braintree * @subpackage Result - * @copyright 2010 Braintree Payment Solutions * * @property-read array $params original passed params - * @property-read object $errors Braintree_Error_ErrorCollection - * @property-read object $creditCardVerification credit card verification data + * @property-read \Braintree\Error\ErrorCollection $errors + * @property-read \Braintree\Result\CreditCardVerification $creditCardVerification credit card verification data */ -class Braintree_Result_Error extends Braintree +class Error extends Base { - /** - * - * @var boolean always false + /** + * @var bool always false */ public $success = false; @@ -54,10 +53,10 @@ public function valueForHtmlField($field) $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY); $params = $this->params; foreach(array_slice($pieces, 0, -1) as $key) { - $params = $params[Braintree_Util::delimiterToCamelCase($key)]; + $params = $params[Util::delimiterToCamelCase($key)]; } if ($key != 'custom_fields') { - $finalKey = Braintree_Util::delimiterToCamelCase(end($pieces)); + $finalKey = Util::delimiterToCamelCase(end($pieces)); } else { $finalKey = end($pieces); } @@ -73,45 +72,52 @@ public function valueForHtmlField($field) public function __construct($response) { $this->_attributes = $response; - $this->_set('errors', new Braintree_Error_ErrorCollection($response['errors'])); + $this->_set('errors', new ErrorCollection($response['errors'])); if(isset($response['verification'])) { - $this->_set('creditCardVerification', new Braintree_Result_CreditCardVerification($response['verification'])); + $this->_set('creditCardVerification', new CreditCardVerification($response['verification'])); } else { $this->_set('creditCardVerification', null); } if(isset($response['transaction'])) { - $this->_set('transaction', Braintree_Transaction::factory($response['transaction'])); + $this->_set('transaction', Transaction::factory($response['transaction'])); } else { $this->_set('transaction', null); } if(isset($response['subscription'])) { - $this->_set('subscription', Braintree_Subscription::factory($response['subscription'])); + $this->_set('subscription', Subscription::factory($response['subscription'])); } else { $this->_set('subscription', null); } if(isset($response['merchantAccount'])) { - $this->_set('merchantAccount', Braintree_MerchantAccount::factory($response['merchantAccount'])); + $this->_set('merchantAccount', MerchantAccount::factory($response['merchantAccount'])); } else { $this->_set('merchantAccount', null); } + + if(isset($response['verification'])) { + $this->_set('verification', new CreditCardVerification($response['verification'])); + } else { + $this->_set('verification', null); + } } /** * create a printable representation of the object as: * ClassName[property=value, property=value] * @ignore - * @return var + * @return string */ public function __toString() { - $output = Braintree_Util::attributesToString($this->_attributes); + $output = Util::attributesToString($this->_attributes); if (isset($this->_creditCardVerification)) { $output .= sprintf('%s', $this->_creditCardVerification); } - return __CLASS__ .'['.$output.']'; + return __CLASS__ .'[' . $output . ']'; } } +class_alias('Braintree\Result\Error', 'Braintree_Result_Error'); diff --git a/lib/Braintree/Result/Successful.php b/lib/Braintree/Result/Successful.php index 8b7d16c..69f087c 100644 --- a/lib/Braintree/Result/Successful.php +++ b/lib/Braintree/Result/Successful.php @@ -1,11 +1,8 @@ customer like so: * * - * $result = Braintree_Customer::create(array('first_name' => "John")); + * $result = Customer::create(array('first_name' => "John")); * if ($result->success) { - * // Braintree_Result_Successful + * // Successful * echo "Created customer {$result->customer->id}"; * } else { - * // Braintree_Result_Error + * // Error * } * * * * @package Braintree * @subpackage Result - * @copyright 2010 Braintree Payment Solutions */ -class Braintree_Result_Successful extends Braintree_Instance +class Successful extends Instance { /** * @@ -42,28 +38,33 @@ class Braintree_Result_Successful extends Braintree_Instance * * @var string stores the internal name of the object providing access to */ - private $_returnObjectName; + private $_returnObjectNames; /** * @ignore - * @param string $classToReturn name of class to instantiate + * @param array|null $objsToReturn + * @param array|null $propertyNames */ - public function __construct($objToReturn = null) + public function __construct($objsToReturn = [], $propertyNames = []) { - if(!empty($objToReturn)) { - // get a lowercase direct name for the property - $property = Braintree_Util::cleanClassName( - get_class($objToReturn) - ); + // Sanitize arguments (preserves backwards compatibility) + if (!is_array($objsToReturn)) { $objsToReturn = [$objsToReturn]; } + if (!is_array($propertyNames)) { $propertyNames = [$propertyNames]; } + + $objects = $this->_mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn); + $this->_attributes = []; + $this->_returnObjectNames = []; + + foreach ($objects as $propertyName => $objToReturn) { + // save the name for indirect access - $this->_returnObjectName = $property; + array_push($this->_returnObjectNames, $propertyName); // create the property! - $this->$property = $objToReturn; + $this->$propertyName = $objToReturn; } } - /** * * @ignore @@ -71,8 +72,21 @@ public function __construct($objToReturn = null) */ public function __toString() { - $returnObject = $this->_returnObjectName; - return __CLASS__ . '['.$this->$returnObject->__toString().']'; + $objects = []; + foreach ($this->_returnObjectNames as $returnObjectName) { + array_push($objects, $returnObjectName); + } + return __CLASS__ . '[' . implode(', ', $objects) . ']'; } + private function _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn) { + if(count($objsToReturn) != count($propertyNames)) { + $propertyNames = []; + foreach ($objsToReturn as $obj) { + array_push($propertyNames, Util::cleanClassName(get_class($obj))); + } + } + return array_combine($propertyNames, $objsToReturn); + } } +class_alias('Braintree\Result\Successful', 'Braintree_Result_Successful'); diff --git a/lib/Braintree/Result/UsBankAccountVerification.php b/lib/Braintree/Result/UsBankAccountVerification.php new file mode 100644 index 0000000..3c94c9b --- /dev/null +++ b/lib/Braintree/Result/UsBankAccountVerification.php @@ -0,0 +1,112 @@ +_initializeFromArray($attributes); + + $usBankAccount = isset($attributes['usBankAccount']) ? + UsBankAccount::factory($attributes['usBankAccount']) : + null; + $this->usBankAccount = $usBankAccount; + } + + /** + * initializes instance properties from the keys/values of an array + * @ignore + * @access protected + * @param $aAttribs array of properties to set - single level + * @return void + */ + private function _initializeFromArray($attributes) + { + $this->_attributes = $attributes; + foreach($attributes AS $name => $value) { + $varName = "_$name"; + $this->$varName = $value; + } + } + + /** + * @ignore + */ + public function __get($name) + { + $varName = "_$name"; + return isset($this->$varName) ? $this->$varName : null; + } + + /** + * returns a string representation of the customer + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } + + public static function allStatuses() + { + return [ + UsBankAccountVerification::FAILED, + UsBankAccountVerification::GATEWAY_REJECTED, + UsBankAccountVerification::PROCESSOR_DECLINED, + UsBankAccountVerification::VERIFIED, + UsBankAccountVerification::PENDING, + ]; + } + + public static function allVerificationMethods() + { + return [ + UsBankAccountVerification::TOKENIZED_CHECK, + UsBankAccountVerification::NETWORK_CHECK, + UsBankAccountVerification::INDEPENDENT_CHECK, + UsBankAccountVerification::MICRO_TRANSFERS, + ]; + } +} +class_alias('Braintree\Result\UsBankAccountVerification', 'Braintree_Result_UsBankAccountVerification'); diff --git a/lib/Braintree/RiskData.php b/lib/Braintree/RiskData.php new file mode 100644 index 0000000..971d805 --- /dev/null +++ b/lib/Braintree/RiskData.php @@ -0,0 +1,30 @@ +_initialize($attributes); + + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } + + /** + * returns a string representation of the risk data + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + +} +class_alias('Braintree\RiskData', 'Braintree_RiskData'); diff --git a/lib/Braintree/SamsungPayCard.php b/lib/Braintree/SamsungPayCard.php new file mode 100644 index 0000000..ab77172 --- /dev/null +++ b/lib/Braintree/SamsungPayCard.php @@ -0,0 +1,138 @@ +default; + } + + /** + * checks whether the card is expired based on the current date + * + * @return boolean + */ + public function isExpired() + { + return $this->expired; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $creditCardAttribs array of creditcard data + * @return void + */ + protected function _initialize($creditCardAttribs) + { + // set the attributes + $this->_attributes = $creditCardAttribs; + + // map each address into its own object + $billingAddress = isset($creditCardAttribs['billingAddress']) ? + Address::factory($creditCardAttribs['billingAddress']) : + null; + + $subscriptionArray = []; + if (isset($creditCardAttribs['subscriptions'])) { + foreach ($creditCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + $this->_set('billingAddress', $billingAddress); + $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); + $this->_set('maskedNumber', $this->bin . '******' . $this->last4); + } + + /** + * returns false if comparing object is not a SamsungPayCard, + * or is a SamsungPayCard with a different id + * + * @param object $otherSamsungPayCard customer to compare against + * @return boolean + */ + public function isEqual($otherSamsungPayCard) + { + return !($otherSamsungPayCard instanceof self) ? false : $this->token === $otherSamsungPayCard->token; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + + /** + * factory method: returns an instance of SamsungPayCard + * to the requesting method, with populated properties + * + * @ignore + * @return SamsungPayCard + */ + public static function factory($attributes) + { + $defaultAttributes = [ + 'bin' => '', + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => '', + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } +} +class_alias('Braintree\SamsungPayCard', 'Braintree_SamsungPayCard'); diff --git a/lib/Braintree/SettlementBatchSummary.php b/lib/Braintree/SettlementBatchSummary.php index 98591a7..3a270a8 100644 --- a/lib/Braintree/SettlementBatchSummary.php +++ b/lib/Braintree/SettlementBatchSummary.php @@ -1,57 +1,13 @@ $settlement_date); - if (isset($groupByCustomField)) - { - $criteria['group_by_custom_field'] = $groupByCustomField; - } - $params = array('settlement_batch_summary' => $criteria); - $response = Braintree_Http::post('/settlement_batch_summary', $params); - - if (isset($groupByCustomField)) - { - $response['settlementBatchSummary']['records'] = self::_underscoreCustomField( - $groupByCustomField, - $response['settlementBatchSummary']['records'] - ); - } - - return self::_verifyGatewayResponse($response); - } - - private static function _underscoreCustomField($groupByCustomField, $records) - { - $updatedRecords = array(); - - foreach ($records as $record) - { - $camelized = Braintree_Util::delimiterToCamelCase($groupByCustomField); - $record[$groupByCustomField] = $record[$camelized]; - unset($record[$camelized]); - $updatedRecords[] = $record; - } - - return $updatedRecords; - } - - private static function _verifyGatewayResponse($response) - { - if (isset($response['settlementBatchSummary'])) { - return new Braintree_Result_Successful( - self::factory($response['settlementBatchSummary']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected settlementBatchSummary or apiErrorResponse" - ); - } - } +namespace Braintree; +class SettlementBatchSummary extends Base +{ + /** + * + * @param array $attributes + * @return SettlementBatchSummary + */ public static function factory($attributes) { $instance = new self(); @@ -61,6 +17,7 @@ public static function factory($attributes) /** * @ignore + * @param array $attributes */ protected function _initialize($attributes) { @@ -71,4 +28,18 @@ public function records() { return $this->_attributes['records']; } + + + /** + * static method redirecting to gateway + * + * @param string $settlement_date Date YYYY-MM-DD + * @param string $groupByCustomField + * @return Result\Successful|Result\Error + */ + public static function generate($settlement_date, $groupByCustomField = NULL) + { + return Configuration::gateway()->settlementBatchSummary()->generate($settlement_date, $groupByCustomField); + } } +class_alias('Braintree\SettlementBatchSummary', 'Braintree_SettlementBatchSummary'); diff --git a/lib/Braintree/SettlementBatchSummaryGateway.php b/lib/Braintree/SettlementBatchSummaryGateway.php new file mode 100644 index 0000000..e70db87 --- /dev/null +++ b/lib/Braintree/SettlementBatchSummaryGateway.php @@ -0,0 +1,106 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /** + * + * @param string $settlement_date + * @param string $groupByCustomField + * @return SettlementBatchSummary|Result\Error + */ + public function generate($settlement_date, $groupByCustomField = NULL) + { + $criteria = ['settlement_date' => $settlement_date]; + if (isset($groupByCustomField)) + { + $criteria['group_by_custom_field'] = $groupByCustomField; + } + $params = ['settlement_batch_summary' => $criteria]; + $path = $this->_config->merchantPath() . '/settlement_batch_summary'; + $response = $this->_http->post($path, $params); + + if (isset($groupByCustomField)) + { + $response['settlementBatchSummary']['records'] = $this->_underscoreCustomField( + $groupByCustomField, + $response['settlementBatchSummary']['records'] + ); + } + + return $this->_verifyGatewayResponse($response); + } + + /** + * + * @param string $groupByCustomField + * @param array $records + * @return array + */ + private function _underscoreCustomField($groupByCustomField, $records) + { + $updatedRecords = []; + + foreach ($records as $record) + { + $camelized = Util::delimiterToCamelCase($groupByCustomField); + $record[$groupByCustomField] = $record[$camelized]; + unset($record[$camelized]); + $updatedRecords[] = $record; + } + + return $updatedRecords; + } + + /** + * + * @param array $response + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['settlementBatchSummary'])) { + return new Result\Successful( + SettlementBatchSummary::factory($response['settlementBatchSummary']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected settlementBatchSummary or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\SettlementBatchSummaryGateway', 'Braintree_SettlementBatchSummaryGateway'); diff --git a/lib/Braintree/SignatureService.php b/lib/Braintree/SignatureService.php new file mode 100644 index 0000000..5e12369 --- /dev/null +++ b/lib/Braintree/SignatureService.php @@ -0,0 +1,24 @@ +key = $key; + $this->digest = $digest; + } + + public function sign($payload) + { + return $this->hash($payload) . "|" . $payload; + } + + public function hash($data) + { + return call_user_func($this->digest, $this->key, $data); + } + +} +class_alias('Braintree\SignatureService', 'Braintree_SignatureService'); diff --git a/lib/Braintree/Subscription.php b/lib/Braintree/Subscription.php index 12bbb54..b4731a2 100644 --- a/lib/Braintree/Subscription.php +++ b/lib/Braintree/Subscription.php @@ -1,17 +1,18 @@ == More information == * - * For more detailed information on Subscriptions, see {@link http://www.braintreepayments.com/gateway/subscription-api http://www.braintreepaymentsolutions.com/gateway/subscription-api} + * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} * * PHP Version 5 * * @package Braintree - * @copyright 2010 Braintree Payment Solutions */ -class Braintree_Subscription extends Braintree +class Subscription extends Base { const ACTIVE = 'Active'; const CANCELED = 'Canceled'; @@ -19,12 +20,10 @@ class Braintree_Subscription extends Braintree const PAST_DUE = 'Past Due'; const PENDING = 'Pending'; - public static function create($attributes) - { - Braintree_Util::verifyKeys(self::_createSignature(), $attributes); - $response = Braintree_Http::post('/subscriptions', array('subscription' => $attributes)); - return self::_verifyGatewayResponse($response); - } + // Subscription Sources + const API = 'api'; + const CONTROL_PANEL = 'control_panel'; + const RECURRING = 'recurring'; /** * @ignore @@ -37,138 +36,6 @@ public static function factory($attributes) return $instance; } - public static function find($id) - { - self::_validateId($id); - - try { - $response = Braintree_Http::get('/subscriptions/' . $id); - return self::factory($response['subscription']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound('subscription with id ' . $id . ' not found'); - } - - } - - public static function search($query) - { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); - } - - - $response = Braintree_Http::post('/subscriptions/advanced_search_ids', array('search' => $criteria)); - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetch', - 'methodArgs' => array($query) - ); - - return new Braintree_ResourceCollection($response, $pager); - } - - public static function fetch($query, $ids) - { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); - } - $criteria["ids"] = Braintree_SubscriptionSearch::ids()->in($ids)->toparam(); - $response = Braintree_Http::post('/subscriptions/advanced_search', array('search' => $criteria)); - - return Braintree_Util::extractAttributeAsArray( - $response['subscriptions'], - 'subscription' - ); - } - - public static function update($subscriptionId, $attributes) - { - Braintree_Util::verifyKeys(self::_updateSignature(), $attributes); - $response = Braintree_Http::put( - '/subscriptions/' . $subscriptionId, - array('subscription' => $attributes) - ); - return self::_verifyGatewayResponse($response); - } - - public static function retryCharge($subscriptionId, $amount = null) - { - $transaction_params = array('type' => Braintree_Transaction::SALE, - 'subscriptionId' => $subscriptionId); - if (isset($amount)) { - $transaction_params['amount'] = $amount; - } - - $response = Braintree_Http::post( - '/transactions', - array('transaction' => $transaction_params)); - return self::_verifyGatewayResponse($response); - } - - public static function cancel($subscriptionId) - { - $response = Braintree_Http::put('/subscriptions/' . $subscriptionId . '/cancel'); - return self::_verifyGatewayResponse($response); - } - - private static function _createSignature() - { - return array_merge( - array( - 'billingDayOfMonth', - 'firstBillingDate', - 'id', - 'merchantAccountId', - 'neverExpires', - 'numberOfBillingCycles', - 'paymentMethodToken', - 'planId', - 'price', - 'trialDuration', - 'trialDurationUnit', - 'trialPeriod', - array('descriptor' => array('name', 'phone')), - array('options' => array('doNotInheritAddOnsOrDiscounts', 'startImmediately')), - ), - self::_addOnDiscountSignature() - ); - } - - private static function _updateSignature() - { - return array_merge( - array( - 'merchantAccountId', 'numberOfBillingCycles', 'paymentMethodToken', 'planId', - 'id', 'neverExpires', 'price', - array('descriptor' => array('name', 'phone')), - array('options' => array('prorateCharges', 'replaceAllAddOnsAndDiscounts', 'revertSubscriptionOnProrationFailure')), - ), - self::_addOnDiscountSignature() - ); - } - - private static function _addOnDiscountSignature() - { - return array( - array( - 'addOns' => array( - array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')), - array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')), - array('remove' => array('_anyKey_')), - ) - ), - array( - 'discounts' => array( - array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')), - array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')), - array('remove' => array('_anyKey_')), - ) - ) - ); - } - /** * @ignore */ @@ -176,81 +43,102 @@ protected function _initialize($attributes) { $this->_attributes = $attributes; - $addOnArray = array(); + $addOnArray = []; if (isset($attributes['addOns'])) { foreach ($attributes['addOns'] AS $addOn) { - $addOnArray[] = Braintree_AddOn::factory($addOn); + $addOnArray[] = AddOn::factory($addOn); } } $this->_attributes['addOns'] = $addOnArray; - $discountArray = array(); + $discountArray = []; if (isset($attributes['discounts'])) { foreach ($attributes['discounts'] AS $discount) { - $discountArray[] = Braintree_Discount::factory($discount); + $discountArray[] = Discount::factory($discount); } } $this->_attributes['discounts'] = $discountArray; if (isset($attributes['descriptor'])) { - $this->_set('descriptor', new Braintree_Descriptor($attributes['descriptor'])); + $this->_set('descriptor', new Descriptor($attributes['descriptor'])); } - $transactionArray = array(); + if (isset($attributes['description'])) { + $this->_set('description', $attributes['description']); + } + + $statusHistory = []; + if (isset($attributes['statusHistory'])) { + foreach ($attributes['statusHistory'] AS $history) { + $statusHistory[] = new Subscription\StatusDetails($history); + } + } + $this->_attributes['statusHistory'] = $statusHistory; + + $transactionArray = []; if (isset($attributes['transactions'])) { foreach ($attributes['transactions'] AS $transaction) { - $transactionArray[] = Braintree_Transaction::factory($transaction); + $transactionArray[] = Transaction::factory($transaction); } } $this->_attributes['transactions'] = $transactionArray; } /** - * @ignore + * returns a string representation of the customer + * @return string */ - private static function _validateId($id = null) { - if (empty($id)) { - throw new InvalidArgumentException( - 'expected subscription id to be set' - ); - } - if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid subscription id.' - ); + public function __toString() + { + $excludedAttributes = ['statusHistory']; + + $displayAttributes = []; + foreach($this->_attributes as $key => $val) { + if (!in_array($key, $excludedAttributes)) { + $displayAttributes[$key] = $val; + } } + + return __CLASS__ . '[' . + Util::attributesToString($displayAttributes) .']'; } - /** - * @ignore - */ - private static function _verifyGatewayResponse($response) + + + // static methods redirecting to gateway + + public static function create($attributes) { - if (isset($response['subscription'])) { - return new Braintree_Result_Successful( - self::factory($response['subscription']) - ); - } else if (isset($response['transaction'])) { - // return a populated instance of Braintree_Transaction, for subscription retryCharge - return new Braintree_Result_Successful( - Braintree_Transaction::factory($response['transaction']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected subscription, transaction, or apiErrorResponse" - ); - } + return Configuration::gateway()->subscription()->create($attributes); } - /** - * returns a string representation of the customer - * @return string - */ - public function __toString() + public static function find($id) { - return __CLASS__ . '[' . - Braintree_Util::attributesToString($this->_attributes) .']'; + return Configuration::gateway()->subscription()->find($id); + } + + public static function search($query) + { + return Configuration::gateway()->subscription()->search($query); } + public static function fetch($query, $ids) + { + return Configuration::gateway()->subscription()->fetch($query, $ids); + } + + public static function update($subscriptionId, $attributes) + { + return Configuration::gateway()->subscription()->update($subscriptionId, $attributes); + } + + public static function retryCharge($subscriptionId, $amount = null, $submitForSettlement = false) + { + return Configuration::gateway()->subscription()->retryCharge($subscriptionId, $amount, $submitForSettlement); + } + + public static function cancel($subscriptionId) + { + return Configuration::gateway()->subscription()->cancel($subscriptionId); + } } +class_alias('Braintree\Subscription', 'Braintree_Subscription'); diff --git a/lib/Braintree/Subscription/StatusDetails.php b/lib/Braintree/Subscription/StatusDetails.php new file mode 100644 index 0000000..cfd2bda --- /dev/null +++ b/lib/Braintree/Subscription/StatusDetails.php @@ -0,0 +1,24 @@ +== More information == + * + * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} + * + * PHP Version 5 + * + * @package Braintree + */ +class SubscriptionGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function create($attributes) + { + Util::verifyKeys(self::_createSignature(), $attributes); + $path = $this->_config->merchantPath() . '/subscriptions'; + $response = $this->_http->post($path, ['subscription' => $attributes]); + return $this->_verifyGatewayResponse($response); + } + + public function find($id) + { + $this->_validateId($id); + + try { + $path = $this->_config->merchantPath() . '/subscriptions/' . $id; + $response = $this->_http->get($path); + return Subscription::factory($response['subscription']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('subscription with id ' . $id . ' not found'); + } + + } + + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + + + $path = $this->_config->merchantPath() . '/subscriptions/advanced_search_ids'; + $response = $this->_http->post($path, ['search' => $criteria]); + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [$query] + ]; + + return new ResourceCollection($response, $pager); + } + + public function fetch($query, $ids) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + $criteria["ids"] = SubscriptionSearch::ids()->in($ids)->toparam(); + $path = $this->_config->merchantPath() . '/subscriptions/advanced_search'; + $response = $this->_http->post($path, ['search' => $criteria]); + + return Util::extractAttributeAsArray( + $response['subscriptions'], + 'subscription' + ); + } + + public function update($subscriptionId, $attributes) + { + Util::verifyKeys(self::_updateSignature(), $attributes); + $path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId; + $response = $this->_http->put($path, ['subscription' => $attributes]); + return $this->_verifyGatewayResponse($response); + } + + public function retryCharge($subscriptionId, $amount = null, $submitForSettlement = false) + { + $transaction_params = ['type' => Transaction::SALE, + 'subscriptionId' => $subscriptionId]; + if (isset($amount)) { + $transaction_params['amount'] = $amount; + } + if ($submitForSettlement) { + $transaction_params['options'] = ['submitForSettlement' => $submitForSettlement]; + } + + $path = $this->_config->merchantPath() . '/transactions'; + $response = $this->_http->post($path, ['transaction' => $transaction_params]); + return $this->_verifyGatewayResponse($response); + } + + public function cancel($subscriptionId) + { + $path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId . '/cancel'; + $response = $this->_http->put($path); + return $this->_verifyGatewayResponse($response); + } + + private static function _createSignature() + { + return array_merge( + [ + 'billingDayOfMonth', + 'firstBillingDate', + 'createdAt', + 'updatedAt', + 'id', + 'merchantAccountId', + 'neverExpires', + 'numberOfBillingCycles', + 'paymentMethodToken', + 'paymentMethodNonce', + 'planId', + 'price', + 'trialDuration', + 'trialDurationUnit', + 'trialPeriod', + ['descriptor' => ['name', 'phone', 'url']], + ['options' => [ + 'doNotInheritAddOnsOrDiscounts', + 'startImmediately', + ['paypal' => ['description']] + ]], + ], + self::_addOnDiscountSignature() + ); + } + + private static function _updateSignature() + { + return array_merge( + [ + 'merchantAccountId', 'numberOfBillingCycles', 'paymentMethodToken', 'planId', + 'paymentMethodNonce', 'id', 'neverExpires', 'price', + ['descriptor' => ['name', 'phone', 'url']], + ['options' => [ + 'prorateCharges', + 'replaceAllAddOnsAndDiscounts', + 'revertSubscriptionOnProrationFailure', + ['paypal' => ['description']] + ]], + ], + self::_addOnDiscountSignature() + ); + } + + private static function _addOnDiscountSignature() + { + return [ + [ + 'addOns' => [ + ['add' => ['amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity']], + ['update' => ['amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity']], + ['remove' => ['_anyKey_']], + ] + ], + [ + 'discounts' => [ + ['add' => ['amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity']], + ['update' => ['amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity']], + ['remove' => ['_anyKey_']], + ] + ] + ]; + } + + /** + * @ignore + */ + private function _validateId($id = null) { + if (empty($id)) { + throw new InvalidArgumentException( + 'expected subscription id to be set' + ); + } + if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { + throw new InvalidArgumentException( + $id . ' is an invalid subscription id.' + ); + } + } + + /** + * @ignore + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['subscription'])) { + return new Result\Successful( + Subscription::factory($response['subscription']) + ); + } else if (isset($response['transaction'])) { + // return a populated instance of Transaction, for subscription retryCharge + return new Result\Successful( + Transaction::factory($response['transaction']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected subscription, transaction, or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\SubscriptionGateway', 'Braintree_SubscriptionGateway'); diff --git a/lib/Braintree/SubscriptionSearch.php b/lib/Braintree/SubscriptionSearch.php index 01cba1a..ba2a5ef 100644 --- a/lib/Braintree/SubscriptionSearch.php +++ b/lib/Braintree/SubscriptionSearch.php @@ -1,64 +1,72 @@ '378734493671000', 'Discover' => '6011000990139424', 'MasterCard' => '5105105105105100', 'Visa' => '4000111111111115', - ); + ]; + + public static $amexPayWithPoints = [ + 'Success' => "371260714673002", + 'IneligibleCard' => "378267515471109", + 'InsufficientPoints' => "371544868764018", + ]; + public static $disputes = [ + 'Chargeback' => '4023898493988028', + ]; public static function getAll() { return array_merge( self::$amExes, self::$discoverCards, + self::$eloCards, self::$masterCards, self::$visas ); } } +class_alias('Braintree\Test\CreditCardNumbers', 'Braintree_Test_CreditCardNumbers'); diff --git a/lib/Braintree/Test/MerchantAccount.php b/lib/Braintree/Test/MerchantAccount.php index 85a7774..cc00c67 100644 --- a/lib/Braintree/Test/MerchantAccount.php +++ b/lib/Braintree/Test/MerchantAccount.php @@ -1,12 +1,13 @@ testing()->settle($transactionId); + } + + /** + * settlement confirm a transaction by id in sandbox + * + * @param string $id transaction id + * @param Configuration $config gateway config + * @return Transaction + */ + public static function settlementConfirm($transactionId) + { + return Configuration::gateway()->testing()->settlementConfirm($transactionId); + } + + /** + * settlement decline a transaction by id in sandbox + * + * @param string $id transaction id + * @param Configuration $config gateway config + * @return Transaction + */ + public static function settlementDecline($transactionId) + { + return Configuration::gateway()->testing()->settlementDecline($transactionId); + } + + /** + * settlement pending a transaction by id in sandbox + * + * @param string $id transaction id + * @param Configuration $config gateway config + * @return Transaction + */ + public static function settlementPending($transactionId) + { + return Configuration::gateway()->testing()->settlementPending($transactionId); + } +} +class_alias('Braintree\Test\Transaction', 'Braintree_Test_Transaction'); diff --git a/lib/Braintree/Test/TransactionAmounts.php b/lib/Braintree/Test/TransactionAmounts.php index 7dc1a5b..592d70d 100644 --- a/lib/Braintree/Test/TransactionAmounts.php +++ b/lib/Braintree/Test/TransactionAmounts.php @@ -1,11 +1,5 @@ _gateway = $gateway; + $this->_config = $gateway->config; + $this->_http = new Http($this->_config); + } + + public function settle($transactionId) + { + return self::_doTestRequest('/settle', $transactionId); + } + + public function settlementPending($transactionId) + { + return self::_doTestRequest('/settlement_pending', $transactionId); + } + + public function settlementConfirm($transactionId) + { + return self::_doTestRequest('/settlement_confirm', $transactionId); + } + + public function settlementDecline($transactionId) + { + return self::_doTestRequest('/settlement_decline', $transactionId); + } + + private function _doTestRequest($testPath, $transactionId) + { + self::_checkEnvironment(); + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . $testPath; + $response = $this->_http->put($path); + return Transaction::factory($response['transaction']); + } + + private function _checkEnvironment() + { + if (Configuration::$global->getEnvironment() === 'production') { + throw new Exception\TestOperationPerformedInProduction(); + } + } +} +class_alias('Braintree\TestingGateway', 'Braintree_TestingGateway'); diff --git a/lib/Braintree/TextNode.php b/lib/Braintree/TextNode.php index f193d1d..9f932a3 100644 --- a/lib/Braintree/TextNode.php +++ b/lib/Braintree/TextNode.php @@ -1,10 +1,12 @@ searchTerms["contains"] = strval($value); return $this; } } +class_alias('Braintree\TextNode', 'Braintree_TextNode'); diff --git a/lib/Braintree/ThreeDSecureInfo.php b/lib/Braintree/ThreeDSecureInfo.php new file mode 100644 index 0000000..a04ec39 --- /dev/null +++ b/lib/Braintree/ThreeDSecureInfo.php @@ -0,0 +1,30 @@ +_initialize($attributes); + + return $instance; + } + + protected function _initialize($attributes) + { + $this->_attributes = $attributes; + } + + /** + * returns a string representation of the three d secure info + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + +} +class_alias('Braintree\ThreeDSecureInfo', 'Braintree_ThreeDSecureInfo'); diff --git a/lib/Braintree/Transaction.php b/lib/Braintree/Transaction.php index eb9babf..0e82981 100644 --- a/lib/Braintree/Transaction.php +++ b/lib/Braintree/Transaction.php @@ -1,13 +1,8 @@ Minimalistic example: * - * Braintree_Transaction::saleNoValidate(array( + * Transaction::saleNoValidate(array( * 'amount' => '100.00', * 'creditCard' => array( * 'number' => '5105105105105100', @@ -26,7 +21,7 @@ * * Full example: * - * Braintree_Transaction::saleNoValidate(array( + * Transaction::saleNoValidate(array( * 'amount' => '100.00', * 'orderId' => '123', * 'channel' => 'MyShoppingCardProvider', @@ -42,7 +37,7 @@ * 'id' => 'customer_123', * 'firstName' => 'Dan', * 'lastName' => 'Smith', - * 'company' => 'Braintree Payment Solutions', + * 'company' => 'Braintree', * 'email' => 'dan@example.com', * 'phone' => '419-555-1234', * 'fax' => '419-555-1235', @@ -82,7 +77,7 @@ * a transaction can be stored in the vault by setting * transaction[options][storeInVault] to true. * - * $transaction = Braintree_Transaction::saleNoValidate(array( + * $transaction = Transaction::saleNoValidate(array( * 'customer' => array( * 'firstName' => 'Adam', * 'lastName' => 'Williams' @@ -105,7 +100,7 @@ * To also store the billing address in the vault, pass the * addBillingAddressToPaymentMethod option. * - * Braintree_Transaction.saleNoValidate(array( + * Transaction.saleNoValidate(array( * ... * 'options' => array( * 'storeInVault' => true @@ -126,7 +121,7 @@ * $transaction[options][submitForSettlement] to true. * * - * $transaction = Braintree_Transaction::saleNoValidate(array( + * $transaction = Transaction::saleNoValidate(array( * 'amount' => '100.00', * 'creditCard' => array( * 'number' => '5105105105105100', @@ -140,11 +135,10 @@ * * == More information == * - * For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api} + * For more detailed information on Transactions, see {@link https://developers.braintreepayments.com/reference/response/transaction/php https://developers.braintreepayments.com/reference/response/transaction/php} * * @package Braintree * @category Resources - * @copyright 2010 Braintree Payment Solutions * * * @property-read string $avsErrorResponseCode @@ -153,22 +147,35 @@ * @property-read string $cvvResponseCode * @property-read string $id transaction id * @property-read string $amount transaction amount - * @property-read object $billingDetails transaction billing address - * @property-read string $createdAt transaction created timestamp - * @property-read object $creditCardDetails transaction credit card info - * @property-read object $customerDetails transaction customer info + * @property-read Braintree\Transaction\AddressDetails $billingDetails transaction billing address + * @property-read \DateTime $createdAt transaction created DateTime + * @property-read Braintree\ApplePayCardDetails $applePayCardDetails transaction Apple Pay card info + * @property-read Braintree\AndroidPayCardDetails $androidPayCardDetails transaction Android Pay card info + * @property-read Braintree\AmexExpressCheckoutCardDetails $amexExpressCheckoutCardDetails transaction Amex Express Checkout card info + * @property-read Braintree\CreditCardDetails $creditCardDetails transaction credit card info + * @property-read Braintree\CoinbaseDetails $coinbaseDetails transaction Coinbase account info + * @property-read Braintree\MasterpassCardDetails $masterpassCardDetails transaction Masterpass card info + * @property-read Braintree\PayPalDetails $paypalDetails transaction paypal account info + * @property-read Braintree\SamsungPayCardDetails $samsungPayCardDetails transaction Samsung Pay card info + * @property-read Braintree\Transaction\CustomerDetails $customerDetails transaction customer info + * @property-read Braintree\VenmoAccount $venmoAccountDetails transaction Venmo Account info + * @property-read Braintree\IdealPayment $idealPaymentDetails transaction Ideal Payment info + * @property-read Braintree\VisaCheckoutCardDetails $visaCheckoutCardDetails transaction Visa Checkout card info * @property-read array $customFields custom fields passed with the request * @property-read string $processorResponseCode gateway response code - * @property-read object $shippingDetails transaction shipping address + * @property-read string $additionalProcessorResponse raw response from processor + * @property-read Braintree\Transaction\AddressDetails $shippingDetails transaction shipping address * @property-read string $status transaction status * @property-read array $statusHistory array of StatusDetails objects * @property-read string $type transaction type - * @property-read string $updatedAt transaction updated timestamp - * @property-read object $disbursementDetails populated when transaction is disbursed + * @property-read \DateTime $updatedAt transaction updated DateTime + * @property-read Braintree\Disbursement $disbursementDetails populated when transaction is disbursed + * @property-read Braintree\Dispute $disputes populated when transaction is disputed + * @property-read Braintree\AuthorizationAdjustment $authorizationAdjustments populated when a transaction has authorization adjustments created when submitted for settlement * */ -final class Braintree_Transaction extends Braintree +class Transaction extends Base { // Transaction Status const AUTHORIZATION_EXPIRED = 'authorization_expired'; @@ -182,6 +189,9 @@ final class Braintree_Transaction extends Braintree const SUBMITTED_FOR_SETTLEMENT = 'submitted_for_settlement'; const VOIDED = 'voided'; const UNRECOGNIZED = 'unrecognized'; + const SETTLEMENT_DECLINED = 'settlement_declined'; + const SETTLEMENT_PENDING = 'settlement_pending'; + const SETTLEMENT_CONFIRMED = 'settlement_confirmed'; // Transaction Escrow Status const ESCROW_HOLD_PENDING = 'hold_pending'; @@ -204,335 +214,129 @@ final class Braintree_Transaction extends Braintree const RECURRING = 'recurring'; // Gateway Rejection Reason - const AVS = 'avs'; - const AVS_AND_CVV = 'avs_and_cvv'; - const CVV = 'cvv'; - const DUPLICATE = 'duplicate'; - const FRAUD = 'fraud'; - - public static function cloneTransaction($transactionId, $attribs) - { - Braintree_Util::verifyKeys(self::cloneSignature(), $attribs); - return self::_doCreate('/transactions/' . $transactionId . '/clone', array('transactionClone' => $attribs)); - } - - /** - * @ignore - * @access public - * @param array $attribs - * @return object - */ - private static function create($attribs) - { - Braintree_Util::verifyKeys(self::createSignature(), $attribs); - return self::_doCreate('/transactions', array('transaction' => $attribs)); - } + const AVS = 'avs'; + const AVS_AND_CVV = 'avs_and_cvv'; + const CVV = 'cvv'; + const DUPLICATE = 'duplicate'; + const FRAUD = 'fraud'; + const THREE_D_SECURE = 'three_d_secure'; + const APPLICATION_INCOMPLETE = 'application_incomplete'; + + // Industry Types + const LODGING_INDUSTRY = 'lodging'; + const TRAVEL_AND_CRUISE_INDUSTRY = 'travel_cruise'; /** + * sets instance properties from an array of values * * @ignore - * @access public - * @param array $attribs - * @return object - * @throws Braintree_Exception_ValidationError - */ - private static function createNoValidate($attribs) - { - $result = self::create($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - /** - * - * @access public - * @param array $attribs - * @return object - */ - public static function createFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return self::_doCreate( - '/transactions/all/confirm_transparent_redirect_request', - array('id' => $params['id']) - ); - } - /** - * - * @access public - * @param none - * @return string - */ - public static function createTransactionUrl() - { - trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE); - return Braintree_Configuration::merchantUrl() . - '/transactions/all/create_via_transparent_redirect_request'; - } - - public static function cloneSignature() - { - return array('amount', 'channel', array('options' => array('submitForSettlement'))); - } - - /** - * creates a full array signature of a valid gateway request - * @return array gateway request signature format - */ - public static function createSignature() - { - return array( - 'amount', 'customerId', 'merchantAccountId', 'orderId', 'channel', 'paymentMethodToken', 'deviceSessionId', - 'purchaseOrderNumber', 'recurring', 'shippingAddressId', 'taxAmount', 'taxExempt', 'type', 'venmoSdkPaymentMethodCode', - 'serviceFeeAmount', 'deviceData', 'fraudMerchantId', 'billingAddressId', - array('creditCard' => - array('token', 'cardholderName', 'cvv', 'expirationDate', 'expirationMonth', 'expirationYear', 'number'), - ), - array('customer' => - array( - 'id', 'company', 'email', 'fax', 'firstName', - 'lastName', 'phone', 'website'), - ), - array('billing' => - array( - 'firstName', 'lastName', 'company', 'countryName', - 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', - 'extendedAddress', 'locality', 'postalCode', 'region', - 'streetAddress'), - ), - array('shipping' => - array( - 'firstName', 'lastName', 'company', 'countryName', - 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', - 'extendedAddress', 'locality', 'postalCode', 'region', - 'streetAddress'), - ), - array('options' => - array( - 'holdInEscrow', - 'storeInVault', - 'storeInVaultOnSuccess', - 'submitForSettlement', - 'addBillingAddressToPaymentMethod', - 'venmoSdkSession', - 'storeShippingAddressInVault'), - ), - array('customFields' => array('_anyKey_') - ), - array('descriptor' => array('name', 'phone')) - ); - } - - /** - * - * @access public - * @param array $attribs - * @return object - */ - public static function credit($attribs) - { - return self::create(array_merge($attribs, array('type' => Braintree_Transaction::CREDIT))); - } - - /** - * - * @access public - * @param array $attribs - * @return object - * @throws Braintree_Exception_ValidationError + * @access protected + * @param array $transactionAttribs array of transaction data + * @return void */ - public static function creditNoValidate($attribs) + protected function _initialize($transactionAttribs) { - $result = self::credit($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - + $this->_attributes = $transactionAttribs; - /** - * @access public - * - */ - public static function find($id) - { - self::_validateId($id); - try { - $response = Braintree_Http::get('/transactions/'.$id); - return self::factory($response['transaction']); - } catch (Braintree_Exception_NotFound $e) { - throw new Braintree_Exception_NotFound( - 'transaction with id ' . $id . ' not found' + if (isset($transactionAttribs['applePay'])) { + $this->_set('applePayCardDetails', + new Transaction\ApplePayCardDetails( + $transactionAttribs['applePay'] + ) ); } - } - /** - * new sale - * @param array $attribs - * @return array - */ - public static function sale($attribs) - { - return self::create(array_merge(array('type' => Braintree_Transaction::SALE), $attribs)); - } - - /** - * roughly equivalent to the ruby bang method - * @access public - * @param array $attribs - * @return array - * @throws Braintree_Exception_ValidationsFailed - */ - public static function saleNoValidate($attribs) - { - $result = self::sale($attribs); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - - /** - * Returns a ResourceCollection of transactions matching the search query. - * - * If query is a string, the search will be a basic search. - * If query is a hash, the search will be an advanced search. - * For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/transaction-api#searching http://www.braintreepaymentsolutions.com/gateway/transaction-api} - * - * @param mixed $query search query - * @param array $options options such as page number - * @return object Braintree_ResourceCollection - * @throws InvalidArgumentException - */ - public static function search($query) - { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); + if (isset($transactionAttribs['androidPayCard'])) { + $this->_set('androidPayCardDetails', + new Transaction\AndroidPayCardDetails( + $transactionAttribs['androidPayCard'] + ) + ); } - $response = Braintree_Http::post('/transactions/advanced_search_ids', array('search' => $criteria)); - if (array_key_exists('searchResults', $response)) { - $pager = array( - 'className' => __CLASS__, - 'classMethod' => 'fetch', - 'methodArgs' => array($query) - ); - - return new Braintree_ResourceCollection($response, $pager); - } else { - throw new Braintree_Exception_DownForMaintenance(); + if (isset($transactionAttribs['masterpassCard'])) { + $this->_set('masterpassCardDetails', + new Transaction\MasterpassCardDetails( + $transactionAttribs['masterpassCard'] + ) + ); } - } - public static function fetch($query, $ids) - { - $criteria = array(); - foreach ($query as $term) { - $criteria[$term->name] = $term->toparam(); + if (isset($transactionAttribs['visaCheckoutCard'])) { + $this->_set('visaCheckoutCardDetails', + new Transaction\VisaCheckoutCardDetails( + $transactionAttribs['visaCheckoutCard'] + ) + ); } - $criteria["ids"] = Braintree_TransactionSearch::ids()->in($ids)->toparam(); - $response = Braintree_Http::post('/transactions/advanced_search', array('search' => $criteria)); - - return Braintree_Util::extractattributeasarray( - $response['creditCardTransactions'], - 'transaction' - ); - } - /** - * void a transaction by id - * - * @param string $id transaction id - * @return object Braintree_Result_Successful|Braintree_Result_Error - */ - public static function void($transactionId) - { - self::_validateId($transactionId); - - $response = Braintree_Http::put('/transactions/'. $transactionId . '/void'); - return self::_verifyGatewayResponse($response); - } - /** - * - */ - public static function voidNoValidate($transactionId) - { - $result = self::void($transactionId); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - - public static function submitForSettlement($transactionId, $amount = null) - { - self::_validateId($transactionId); - - $response = Braintree_Http::put( - '/transactions/'. $transactionId . '/submit_for_settlement', - array( 'transaction' => array( 'amount' => $amount)) - ); - return self::_verifyGatewayResponse($response); - } - - public static function submitForSettlementNoValidate($transactionId, $amount = null) - { - $result = self::submitForSettlement($transactionId, $amount); - return self::returnObjectOrThrowException(__CLASS__, $result); - } - - public static function holdInEscrow($transactionId) - { - self::_validateId($transactionId); - - $response = Braintree_Http::put( - '/transactions/' . $transactionId . '/hold_in_escrow', - array() - ); - return self::_verifyGatewayResponse($response); - } + if (isset($transactionAttribs['samsungPayCard'])) { + $this->_set('samsungPayCardDetails', + new Transaction\SamsungPayCardDetails( + $transactionAttribs['samsungPayCard'] + ) + ); + } - public static function releaseFromEscrow($transactionId) - { - self::_validateId($transactionId); + if (isset($transactionAttribs['amexExpressCheckoutCard'])) { + $this->_set('amexExpressCheckoutCardDetails', + new Transaction\AmexExpressCheckoutCardDetails( + $transactionAttribs['amexExpressCheckoutCard'] + ) + ); + } - $response = Braintree_Http::put( - '/transactions/' . $transactionId . '/release_from_escrow', - array() - ); - return self::_verifyGatewayResponse($response); - } + if (isset($transactionAttribs['venmoAccount'])) { + $this->_set('venmoAccountDetails', + new Transaction\VenmoAccountDetails( + $transactionAttribs['venmoAccount'] + ) + ); + } - public static function cancelRelease($transactionId) - { - self::_validateId($transactionId); + if (isset($transactionAttribs['creditCard'])) { + $this->_set('creditCardDetails', + new Transaction\CreditCardDetails( + $transactionAttribs['creditCard'] + ) + ); + } - $response = Braintree_Http::put( - '/transactions/' . $transactionId . '/cancel_release', - array() - ); - return self::_verifyGatewayResponse($response); - } + if (isset($transactionAttribs['coinbaseAccount'])) { + $this->_set('coinbaseDetails', + new Transaction\CoinbaseDetails( + $transactionAttribs['coinbaseAccount'] + ) + ); + } + if (isset($transactionAttribs['usBankAccount'])) { + $this->_set('usBankAccount', + new Transaction\UsBankAccountDetails( + $transactionAttribs['usBankAccount'] + ) + ); + } - /** - * sets instance properties from an array of values - * - * @ignore - * @access protected - * @param array $transactionAttribs array of transaction data - * @return none - */ - protected function _initialize($transactionAttribs) - { - $this->_attributes = $transactionAttribs; + if (isset($transactionAttribs['idealPayment'])) { + $this->_set('idealPayment', + new Transaction\IdealPaymentDetails( + $transactionAttribs['idealPayment'] + ) + ); + } - if (isset($transactionAttribs['creditCard'])) { - $this->_set('creditCardDetails', - new Braintree_Transaction_CreditCardDetails( - $transactionAttribs['creditCard'] + if (isset($transactionAttribs['paypal'])) { + $this->_set('paypalDetails', + new Transaction\PayPalDetails( + $transactionAttribs['paypal'] ) ); } if (isset($transactionAttribs['customer'])) { $this->_set('customerDetails', - new Braintree_Transaction_CustomerDetails( + new Transaction\CustomerDetails( $transactionAttribs['customer'] ) ); @@ -540,7 +344,7 @@ protected function _initialize($transactionAttribs) if (isset($transactionAttribs['billing'])) { $this->_set('billingDetails', - new Braintree_Transaction_AddressDetails( + new Transaction\AddressDetails( $transactionAttribs['billing'] ) ); @@ -548,7 +352,7 @@ protected function _initialize($transactionAttribs) if (isset($transactionAttribs['shipping'])) { $this->_set('shippingDetails', - new Braintree_Transaction_AddressDetails( + new Transaction\AddressDetails( $transactionAttribs['shipping'] ) ); @@ -556,7 +360,7 @@ protected function _initialize($transactionAttribs) if (isset($transactionAttribs['subscription'])) { $this->_set('subscriptionDetails', - new Braintree_Transaction_SubscriptionDetails( + new Transaction\SubscriptionDetails( $transactionAttribs['subscription'] ) ); @@ -564,7 +368,7 @@ protected function _initialize($transactionAttribs) if (isset($transactionAttribs['descriptor'])) { $this->_set('descriptor', - new Braintree_Descriptor( + new Descriptor( $transactionAttribs['descriptor'] ) ); @@ -572,34 +376,65 @@ protected function _initialize($transactionAttribs) if (isset($transactionAttribs['disbursementDetails'])) { $this->_set('disbursementDetails', - new Braintree_DisbursementDetails($transactionAttribs['disbursementDetails']) + new DisbursementDetails($transactionAttribs['disbursementDetails']) ); } - $statusHistory = array(); + $disputes = []; + if (isset($transactionAttribs['disputes'])) { + foreach ($transactionAttribs['disputes'] AS $dispute) { + $disputes[] = Dispute::factory($dispute); + } + } + + $this->_set('disputes', $disputes); + + $statusHistory = []; if (isset($transactionAttribs['statusHistory'])) { foreach ($transactionAttribs['statusHistory'] AS $history) { - $statusHistory[] = new Braintree_Transaction_StatusDetails($history); + $statusHistory[] = new Transaction\StatusDetails($history); } } $this->_set('statusHistory', $statusHistory); - $addOnArray = array(); + $addOnArray = []; if (isset($transactionAttribs['addOns'])) { foreach ($transactionAttribs['addOns'] AS $addOn) { - $addOnArray[] = Braintree_AddOn::factory($addOn); + $addOnArray[] = AddOn::factory($addOn); } } $this->_set('addOns', $addOnArray); - $discountArray = array(); + $discountArray = []; if (isset($transactionAttribs['discounts'])) { foreach ($transactionAttribs['discounts'] AS $discount) { - $discountArray[] = Braintree_Discount::factory($discount); + $discountArray[] = Discount::factory($discount); } } $this->_set('discounts', $discountArray); + + $authorizationAdjustments = []; + if (isset($transactionAttribs['authorizationAdjustments'])) { + foreach ($transactionAttribs['authorizationAdjustments'] AS $authorizationAdjustment) { + $authorizationAdjustments[] = AuthorizationAdjustment::factory($authorizationAdjustment); + } + } + + $this->_set('authorizationAdjustments', $authorizationAdjustments); + + if(isset($transactionAttribs['riskData'])) { + $this->_set('riskData', RiskData::factory($transactionAttribs['riskData'])); + } + if(isset($transactionAttribs['threeDSecureInfo'])) { + $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($transactionAttribs['threeDSecureInfo'])); + } + if(isset($transactionAttribs['facilitatedDetails'])) { + $this->_set('facilitatedDetails', FacilitatedDetails::factory($transactionAttribs['facilitatedDetails'])); + } + if(isset($transactionAttribs['facilitatorDetails'])) { + $this->_set('facilitatorDetails', FacilitatorDetails::factory($transactionAttribs['facilitatorDetails'])); + } } /** @@ -609,24 +444,17 @@ protected function _initialize($transactionAttribs) public function __toString() { // array of attributes to print - $display = array( + $display = [ 'id', 'type', 'amount', 'status', 'createdAt', 'creditCardDetails', 'customerDetails' - ); + ]; - $displayAttributes = array(); + $displayAttributes = []; foreach ($display AS $attrib) { $displayAttributes[$attrib] = $this->$attrib; } return __CLASS__ . '[' . - Braintree_Util::attributesToString($displayAttributes) .']'; - } - - public static function refund($transactionId, $amount = null) - { - $params = array('transaction' => array('amount' => $amount)); - $response = Braintree_Http::post('/transactions/' . $transactionId . '/refund', $params); - return self::_verifyGatewayResponse($response); + Util::attributesToString($displayAttributes) .']'; } public function isEqual($otherTx) @@ -641,10 +469,11 @@ public function vaultCreditCard() return null; } else { - return Braintree_CreditCard::find($token); + return CreditCard::find($token); } } + /** @return void|Braintree\Customer */ public function vaultCustomer() { $customerId = $this->customerDetails->id; @@ -652,91 +481,135 @@ public function vaultCustomer() return null; } else { - return Braintree_Customer::find($customerId); + return Customer::find($customerId); } } + /** @return bool */ public function isDisbursed() { return $this->disbursementDetails->isValid(); } + /** @return line items */ + public function lineItems() { + return Configuration::gateway()->transactionLineItem()->findAll($this->id); + } + /** - * sends the create request to the gateway + * factory method: returns an instance of Transaction + * to the requesting method, with populated properties * * @ignore - * @param var $url - * @param array $params - * @return mixed + * @return Transaction */ - public static function _doCreate($url, $params) + public static function factory($attributes) { - $response = Braintree_Http::post($url, $params); + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + + // static methods redirecting to gateway - return self::_verifyGatewayResponse($response); + public static function cloneTransaction($transactionId, $attribs) + { + return Configuration::gateway()->transaction()->cloneTransaction($transactionId, $attribs); } - /** - * verifies that a valid transaction id is being used - * @ignore - * @param string transaction id - * @throws InvalidArgumentException - */ - private static function _validateId($id = null) { - if (empty($id)) { - throw new InvalidArgumentException( - 'expected transaction id to be set' - ); - } - if (!preg_match('/^[0-9a-z]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid transaction id.' - ); - } + public static function createFromTransparentRedirect($queryString) + { + return Configuration::gateway()->transaction()->createFromTransparentRedirect($queryString); } + public static function createTransactionUrl() + { + return Configuration::gateway()->transaction()->createTransactionUrl(); + } - /* private class methods */ + public static function credit($attribs) + { + return Configuration::gateway()->transaction()->credit($attribs); + } - /** - * generic method for validating incoming gateway responses - * - * creates a new Braintree_Transaction object and encapsulates - * it inside a Braintree_Result_Successful object, or - * encapsulates a Braintree_Errors object inside a Result_Error - * alternatively, throws an Unexpected exception if the response is invalid. - * - * @ignore - * @param array $response gateway response values - * @return object Result_Successful or Result_Error - * @throws Braintree_Exception_Unexpected - */ - private static function _verifyGatewayResponse($response) + public static function creditNoValidate($attribs) { - if (isset($response['transaction'])) { - // return a populated instance of Braintree_Transaction - return new Braintree_Result_Successful( - self::factory($response['transaction']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Braintree_Result_Error($response['apiErrorResponse']); - } else { - throw new Braintree_Exception_Unexpected( - "Expected transaction or apiErrorResponse" - ); - } + return Configuration::gateway()->transaction()->creditNoValidate($attribs); } - /** - * factory method: returns an instance of Braintree_Transaction - * to the requesting method, with populated properties - * - * @ignore - * @return object instance of Braintree_Transaction - */ - public static function factory($attributes) + public static function find($id) { - $instance = new self(); - $instance->_initialize($attributes); - return $instance; + return Configuration::gateway()->transaction()->find($id); + } + + public static function sale($attribs) + { + return Configuration::gateway()->transaction()->sale($attribs); + } + + public static function saleNoValidate($attribs) + { + return Configuration::gateway()->transaction()->saleNoValidate($attribs); + } + + public static function search($query) + { + return Configuration::gateway()->transaction()->search($query); + } + + public static function fetch($query, $ids) + { + return Configuration::gateway()->transaction()->fetch($query, $ids); + } + + public static function void($transactionId) + { + return Configuration::gateway()->transaction()->void($transactionId); + } + + public static function voidNoValidate($transactionId) + { + return Configuration::gateway()->transaction()->voidNoValidate($transactionId); + } + + public static function submitForSettlement($transactionId, $amount = null, $attribs = []) + { + return Configuration::gateway()->transaction()->submitForSettlement($transactionId, $amount, $attribs); + } + + public static function submitForSettlementNoValidate($transactionId, $amount = null, $attribs = []) + { + return Configuration::gateway()->transaction()->submitForSettlementNoValidate($transactionId, $amount, $attribs); + } + + public static function updateDetails($transactionId, $attribs = []) + { + return Configuration::gateway()->transaction()->updateDetails($transactionId, $attribs); + } + + public static function submitForPartialSettlement($transactionId, $amount, $attribs = []) + { + return Configuration::gateway()->transaction()->submitForPartialSettlement($transactionId, $amount, $attribs); + } + + public static function holdInEscrow($transactionId) + { + return Configuration::gateway()->transaction()->holdInEscrow($transactionId); + } + + public static function releaseFromEscrow($transactionId) + { + return Configuration::gateway()->transaction()->releaseFromEscrow($transactionId); + } + + public static function cancelRelease($transactionId) + { + return Configuration::gateway()->transaction()->cancelRelease($transactionId); + } + + public static function refund($transactionId, $amount = null) + { + return Configuration::gateway()->transaction()->refund($transactionId, $amount); } } +class_alias('Braintree\Transaction', 'Braintree_Transaction'); diff --git a/lib/Braintree/Transaction/AddressDetails.php b/lib/Braintree/Transaction/AddressDetails.php index dc89573..597a208 100644 --- a/lib/Braintree/Transaction/AddressDetails.php +++ b/lib/Braintree/Transaction/AddressDetails.php @@ -1,11 +1,7 @@ _attributes['cardType'] = $this->virtualCardType; + $this->_attributes['last4'] = $this->virtualCardLast4; + } +} +class_alias('Braintree\Transaction\AndroidPayCardDetails', 'Braintree_Transaction_AndroidPayCardDetails'); diff --git a/lib/Braintree/Transaction/ApplePayCardDetails.php b/lib/Braintree/Transaction/ApplePayCardDetails.php new file mode 100644 index 0000000..f0a2be4 --- /dev/null +++ b/lib/Braintree/Transaction/ApplePayCardDetails.php @@ -0,0 +1,39 @@ +_attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; + $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; + + } +} +class_alias('Braintree\Transaction\MasterpassCardDetails', 'Braintree_Transaction_MasterpassCardDetails'); diff --git a/lib/Braintree/Transaction/PayPalDetails.php b/lib/Braintree/Transaction/PayPalDetails.php new file mode 100644 index 0000000..0310aac --- /dev/null +++ b/lib/Braintree/Transaction/PayPalDetails.php @@ -0,0 +1,41 @@ +_attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; + $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; + + } +} +class_alias('Braintree\Transaction\SamsungPayCardDetails', 'Braintree_Transaction_SamsungPayCardDetails'); diff --git a/lib/Braintree/Transaction/StatusDetails.php b/lib/Braintree/Transaction/StatusDetails.php index c105ced..b8e1f8f 100644 --- a/lib/Braintree/Transaction/StatusDetails.php +++ b/lib/Braintree/Transaction/StatusDetails.php @@ -1,25 +1,21 @@ achMandate = $achMandate; + } +} +class_alias('Braintree\Transaction\UsBankAccountDetails', 'Braintree_Transaction_UsBankAccountDetails'); diff --git a/lib/Braintree/Transaction/VenmoAccountDetails.php b/lib/Braintree/Transaction/VenmoAccountDetails.php new file mode 100644 index 0000000..b48baed --- /dev/null +++ b/lib/Braintree/Transaction/VenmoAccountDetails.php @@ -0,0 +1,38 @@ +_attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; + $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; + + } +} +class_alias('Braintree\Transaction\VisaCheckoutCardDetails', 'Braintree_Transaction_VisaCheckoutCardDetails'); diff --git a/lib/Braintree/TransactionGateway.php b/lib/Braintree/TransactionGateway.php new file mode 100644 index 0000000..6d3d739 --- /dev/null +++ b/lib/Braintree/TransactionGateway.php @@ -0,0 +1,550 @@ +== More information == + * + * For more detailed information on Transactions, see {@link https://developers.braintreepayments.com/reference/response/transaction/php https://developers.braintreepayments.com/reference/response/transaction/php} + * + * @package Braintree + * @category Resources + */ + +class TransactionGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + public function cloneTransaction($transactionId, $attribs) + { + Util::verifyKeys(self::cloneSignature(), $attribs); + return $this->_doCreate('/transactions/' . $transactionId . '/clone', ['transactionClone' => $attribs]); + } + + /** + * @ignore + * @access private + * @param array $attribs + * @return Result\Successful|Result\Error + */ + private function create($attribs) + { + Util::verifyKeys(self::createSignature(), $attribs); + return $this->_doCreate('/transactions', ['transaction' => $attribs]); + } + + /** + * @ignore + * @access private + * @param array $attribs + * @return object + * @throws Exception\ValidationError + */ + private function createNoValidate($attribs) + { + $result = $this->create($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + /** + * + * @deprecated since version 2.3.0 + * @access public + * @param array $attribs + * @return object + */ + public function createFromTransparentRedirect($queryString) + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + return $this->_doCreate( + '/transactions/all/confirm_transparent_redirect_request', + ['id' => $params['id']] + ); + } + /** + * + * @deprecated since version 2.3.0 + * @access public + * @param none + * @return string + */ + public function createTransactionUrl() + { + trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); + return $this->_config->baseUrl() . $this->_config->merchantPath() . + '/transactions/all/create_via_transparent_redirect_request'; + } + + public static function cloneSignature() + { + return ['amount', 'channel', ['options' => ['submitForSettlement']]]; + } + + /** + * creates a full array signature of a valid gateway request + * @return array gateway request signature format + */ + public static function createSignature() + { + return [ + 'amount', + 'billingAddressId', + 'channel', + 'customerId', + 'deviceData', + 'deviceSessionId', + 'fraudMerchantId', + 'merchantAccountId', + 'orderId', + 'paymentMethodNonce', + 'paymentMethodToken', + 'purchaseOrderNumber', + 'recurring', + 'serviceFeeAmount', + 'sharedPaymentMethodToken', + 'sharedPaymentMethodNonce', + 'sharedCustomerId', + 'sharedShippingAddressId', + 'sharedBillingAddressId', + 'shippingAddressId', + 'taxAmount', + 'taxExempt', + 'threeDSecureToken', + 'transactionSource', + 'type', + 'venmoSdkPaymentMethodCode', + 'shippingAmount', + 'discountAmount', + 'shipsFromPostalCode', + ['riskData' => + ['customerBrowser', 'customerIp', 'customer_browser', 'customer_ip'] + ], + ['creditCard' => + ['token', 'cardholderName', 'cvv', 'expirationDate', 'expirationMonth', 'expirationYear', 'number'], + ], + ['customer' => + [ + 'id', 'company', 'email', 'fax', 'firstName', + 'lastName', 'phone', 'website'], + ], + ['billing' => + [ + 'firstName', 'lastName', 'company', 'countryName', + 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'extendedAddress', 'locality', 'postalCode', 'region', + 'streetAddress'], + ], + ['shipping' => + [ + 'firstName', 'lastName', 'company', 'countryName', + 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', + 'extendedAddress', 'locality', 'postalCode', 'region', + 'streetAddress'], + ], + ['threeDSecurePassThru' => + [ + 'eciFlag', + 'cavv', + 'xid'], + ], + ['options' => + [ + 'holdInEscrow', + 'storeInVault', + 'storeInVaultOnSuccess', + 'submitForSettlement', + 'addBillingAddressToPaymentMethod', + 'venmoSdkSession', + 'storeShippingAddressInVault', + 'payeeId', + 'payeeEmail', + 'skipAdvancedFraudChecking', + 'skipAvs', + 'skipCvv', + ['threeDSecure' => + ['required'] + ], + # TODO: Snake case version included for backwards compatiblity. Remove in the next major version + ['three_d_secure' => + ['required'] + ], + ['paypal' => + [ + 'payeeId', + 'payeeEmail', + 'customField', + 'description', + ['supplementaryData' => ['_anyKey_']], + ] + ], + ['amexRewards' => + [ + 'requestId', + 'points', + 'currencyAmount', + 'currencyIsoCode' + ] + ], + ['venmo' => + [ + # TODO: Snake case version included for backwards compatiblity. Remove in the next major version + 'profile_id', + 'profileId' + ] + ] + ], + ], + ['customFields' => ['_anyKey_']], + ['descriptor' => ['name', 'phone', 'url']], + ['paypalAccount' => ['payeeId', 'payeeEmail']], + # TODO: Snake case version included for backwards compatiblity. Remove in the next major version + ['apple_pay_card' => ['number', 'cardholder_name', 'cryptogram', 'expiration_month', 'expiration_year', 'eci_indicator']], + + ['applePayCard' => ['number', 'cardholderName', 'cryptogram', 'expirationMonth', 'expirationYear', 'eciIndicator']], + ['industry' => + ['industryType', + ['data' => + [ + 'folioNumber', + 'checkInDate', + 'checkOutDate', + 'travelPackage', + 'departureDate', + 'lodgingCheckInDate', + 'lodgingCheckOutDate', + 'lodgingName', + 'roomRate' + ] + ] + ] + ], + ['lineItems' => ['quantity', 'name', 'description', 'kind', 'unitAmount', 'unitTaxAmount', 'totalAmount', 'discountAmount', 'taxAmount', 'unitOfMeasure', 'productCode', 'commodityCode', 'url']], + ['externalVault' => + ['status' , 'previousNetworkTransactionId'], + ] + ]; + } + + public static function submitForSettlementSignature() + { + return ['orderId', ['descriptor' => ['name', 'phone', 'url']]]; + } + + public static function updateDetailsSignature() + { + return ['amount', 'orderId', ['descriptor' => ['name', 'phone', 'url']]]; + } + + public static function refundSignature() + { + return ['amount', 'orderId']; + } + + /** + * + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function credit($attribs) + { + return $this->create(array_merge($attribs, ['type' => Transaction::CREDIT])); + } + + /** + * + * @access public + * @param array $attribs + * @return Result\Successful|Result\Error + * @throws Exception\ValidationError + */ + public function creditNoValidate($attribs) + { + $result = $this->credit($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + + /** + * @access public + * @param string id + * @return Transaction + */ + public function find($id) + { + $this->_validateId($id); + try { + $path = $this->_config->merchantPath() . '/transactions/' . $id; + $response = $this->_http->get($path); + return Transaction::factory($response['transaction']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'transaction with id ' . $id . ' not found' + ); + } + } + /** + * new sale + * @param array $attribs + * @return Result\Successful|Result\Error + */ + public function sale($attribs) + { + return $this->create(array_merge(['type' => Transaction::SALE], $attribs)); + } + + /** + * roughly equivalent to the ruby bang method + * @access public + * @param array $attribs + * @return array + * @throws Exception\ValidationsFailed + */ + public function saleNoValidate($attribs) + { + $result = $this->sale($attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + + /** + * Returns a ResourceCollection of transactions matching the search query. + * + * If query is a string, the search will be a basic search. + * If query is a hash, the search will be an advanced search. + * For more detailed information and examples, see {@link https://developers.braintreepayments.com/reference/request/transaction/search/php https://developers.braintreepayments.com/reference/request/transaction/search/php} + * + * @param mixed $query search query + * @param array $options options such as page number + * @return ResourceCollection + * @throws InvalidArgumentException + */ + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + + $path = $this->_config->merchantPath() . '/transactions/advanced_search_ids'; + $response = $this->_http->post($path, ['search' => $criteria]); + if (array_key_exists('searchResults', $response)) { + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [$query] + ]; + + return new ResourceCollection($response, $pager); + } else { + throw new Exception\DownForMaintenance(); + } + } + + public function fetch($query, $ids) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + $criteria["ids"] = TransactionSearch::ids()->in($ids)->toparam(); + $path = $this->_config->merchantPath() . '/transactions/advanced_search'; + $response = $this->_http->post($path, ['search' => $criteria]); + + if (array_key_exists('creditCardTransactions', $response)) { + return Util::extractattributeasarray( + $response['creditCardTransactions'], + 'transaction' + ); + } else { + throw new Exception\DownForMaintenance(); + } + } + + /** + * void a transaction by id + * + * @param string $id transaction id + * @return Result\Successful|Result\Error + */ + public function void($transactionId) + { + $this->_validateId($transactionId); + + $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/void'; + $response = $this->_http->put($path); + return $this->_verifyGatewayResponse($response); + } + /** + * + */ + public function voidNoValidate($transactionId) + { + $result = $this->void($transactionId); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + + public function submitForSettlement($transactionId, $amount = null, $attribs = []) + { + $this->_validateId($transactionId); + Util::verifyKeys(self::submitForSettlementSignature(), $attribs); + $attribs['amount'] = $amount; + + $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_settlement'; + $response = $this->_http->put($path, ['transaction' => $attribs]); + return $this->_verifyGatewayResponse($response); + } + + public function submitForSettlementNoValidate($transactionId, $amount = null, $attribs = []) + { + $result = $this->submitForSettlement($transactionId, $amount, $attribs); + return Util::returnObjectOrThrowException(__CLASS__, $result); + } + + public function updateDetails($transactionId, $attribs = []) + { + $this->_validateId($transactionId); + Util::verifyKeys(self::updateDetailsSignature(), $attribs); + + $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/update_details'; + $response = $this->_http->put($path, ['transaction' => $attribs]); + return $this->_verifyGatewayResponse($response); + } + + public function submitForPartialSettlement($transactionId, $amount, $attribs = []) + { + $this->_validateId($transactionId); + Util::verifyKeys(self::submitForSettlementSignature(), $attribs); + $attribs['amount'] = $amount; + + $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_partial_settlement'; + $response = $this->_http->post($path, ['transaction' => $attribs]); + return $this->_verifyGatewayResponse($response); + } + + public function holdInEscrow($transactionId) + { + $this->_validateId($transactionId); + + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/hold_in_escrow'; + $response = $this->_http->put($path, []); + return $this->_verifyGatewayResponse($response); + } + + public function releaseFromEscrow($transactionId) + { + $this->_validateId($transactionId); + + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/release_from_escrow'; + $response = $this->_http->put($path, []); + return $this->_verifyGatewayResponse($response); + } + + public function cancelRelease($transactionId) + { + $this->_validateId($transactionId); + + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/cancel_release'; + $response = $this->_http->put($path, []); + return $this->_verifyGatewayResponse($response); + } + + public function refund($transactionId, $amount_or_options = null) + { + self::_validateId($transactionId); + + if(gettype($amount_or_options) == "array") { + $options = $amount_or_options; + } else { + $options = [ + "amount" => $amount_or_options + ]; + } + Util::verifyKeys(self::refundSignature(), $options); + + $params = ['transaction' => $options]; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/refund'; + $response = $this->_http->post($path, $params); + return $this->_verifyGatewayResponse($response); + } + + /** + * sends the create request to the gateway + * + * @ignore + * @param var $subPath + * @param array $params + * @return Result\Successful|Result\Error + */ + public function _doCreate($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGatewayResponse($response); + } + + /** + * verifies that a valid transaction id is being used + * @ignore + * @param string transaction id + * @throws InvalidArgumentException + */ + private function _validateId($id = null) { + if (empty($id)) { + throw new InvalidArgumentException( + 'expected transaction id to be set' + ); + } + if (!preg_match('/^[0-9a-z]+$/', $id)) { + throw new InvalidArgumentException( + $id . ' is an invalid transaction id.' + ); + } + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new Transaction object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['transaction'])) { + // return a populated instance of Transaction + return new Result\Successful( + Transaction::factory($response['transaction']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + "Expected transaction or apiErrorResponse" + ); + } + } +} +class_alias('Braintree\TransactionGateway', 'Braintree_TransactionGateway'); diff --git a/lib/Braintree/TransactionLineItem.php b/lib/Braintree/TransactionLineItem.php new file mode 100644 index 0000000..39ae828 --- /dev/null +++ b/lib/Braintree/TransactionLineItem.php @@ -0,0 +1,54 @@ +transactionLineItem()->findAll($transactionId); + } +} +class_alias('Braintree\TransactionLineItem', 'Braintree_TransactionLineItem'); +class_alias('Braintree\TransactionLineItem', 'Braintree\Transaction\LineItem'); +class_alias('Braintree\TransactionLineItem', 'Braintree_Transaction_LineItem'); diff --git a/lib/Braintree/TransactionLineItemGateway.php b/lib/Braintree/TransactionLineItemGateway.php new file mode 100644 index 0000000..7b1db2f --- /dev/null +++ b/lib/Braintree/TransactionLineItemGateway.php @@ -0,0 +1,67 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /** + * @access public + * @param string id + * @return Transaction + */ + public function findAll($id) + { + $this->_validateId($id); + try { + $path = $this->_config->merchantPath() . '/transactions/' . $id . '/line_items'; + $response = $this->_http->get($path); + + $lineItems = []; + if (isset($response['lineItems'])) { + foreach ($response['lineItems'] AS $lineItem) { + $lineItems[] = new TransactionLineItem($lineItem); + } + } + return $lineItems; + } catch (Exception\NotFound $e) { + throw new Exception\NotFound('transaction line items with id ' . $id . ' not found'); + } + } + + /** + * verifies that a valid transaction id is being used + * @ignore + * @param string transaction id + * @throws InvalidArgumentException + */ + private function _validateId($id = null) { + if (empty($id)) { + throw new InvalidArgumentException('expected transaction id to be set'); + } + if (!preg_match('/^[0-9a-z]+$/', $id)) { + throw new InvalidArgumentException($id . ' is an invalid transaction id.'); + } + } +} +class_alias('Braintree\TransactionLineItemGateway', 'Braintree_TransactionLineItemGateway'); diff --git a/lib/Braintree/TransactionSearch.php b/lib/Braintree/TransactionSearch.php index 487d781..5271b0b 100644 --- a/lib/Braintree/TransactionSearch.php +++ b/lib/Braintree/TransactionSearch.php @@ -1,125 +1,131 @@ - * $trData = Braintree_TransparentRedirect::createCustomerData(array( + * $trData = TransparentRedirect::createCustomerData(array( * 'redirectUrl => 'http://example.com/redirect_back_to_merchant_site', * )); * @@ -32,7 +25,7 @@ * amount, include the amount in the trData. * * - * $trData = Braintree_TransparentRedirect::transactionData(array( + * $trData = TransparentRedirect::transactionData(array( * 'redirectUrl' => 'http://example.com/complete_transaction', * 'transaction' => array('amount' => '100.00'), * )); @@ -41,9 +34,8 @@ * * @package Braintree * @category Resources - * @copyright 2010 Braintree Payment Solutions */ -class Braintree_TransparentRedirect +class TransparentRedirect { // Request Kinds const CREATE_TRANSACTION = 'create_transaction'; @@ -52,276 +44,57 @@ class Braintree_TransparentRedirect const CREATE_CUSTOMER = 'create_customer'; const UPDATE_CUSTOMER = 'update_customer'; - /** - * - * @ignore - */ - private static $_transparentRedirectKeys = 'redirectUrl'; - private static $_createCustomerSignature; - private static $_updateCustomerSignature; - private static $_transactionSignature; - private static $_createCreditCardSignature; - private static $_updateCreditCardSignature; - - /** * @ignore * don't permit an explicit call of the constructor! - * (like $t = new Braintree_TransparentRedirect()) + * (like $t = new TransparentRedirect()) */ protected function __construct() { } - /** - * create signatures for different call types - * @ignore - */ - public static function init() - { - self::$_createCustomerSignature = array( - self::$_transparentRedirectKeys, - array('customer' => Braintree_Customer::createSignature()), - ); - self::$_updateCustomerSignature = array( - self::$_transparentRedirectKeys, - 'customerId', - array('customer' => Braintree_Customer::updateSignature()), - ); - self::$_transactionSignature = array( - self::$_transparentRedirectKeys, - array('transaction' => Braintree_Transaction::createSignature()), - ); - self::$_createCreditCardSignature = array( - self::$_transparentRedirectKeys, - array('creditCard' => Braintree_CreditCard::createSignature()), - ); - self::$_updateCreditCardSignature = array( - self::$_transparentRedirectKeys, - 'paymentMethodToken', - array('creditCard' => Braintree_CreditCard::updateSignature()), - ); - } + // static methods redirecting to gateway public static function confirm($queryString) { - $params = Braintree_TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - $confirmationKlasses = array( - Braintree_TransparentRedirect::CREATE_TRANSACTION => 'Braintree_Transaction', - Braintree_TransparentRedirect::CREATE_CUSTOMER => 'Braintree_Customer', - Braintree_TransparentRedirect::UPDATE_CUSTOMER => 'Braintree_Customer', - Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD => 'Braintree_CreditCard', - Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD => 'Braintree_CreditCard' - ); - return call_user_func(array($confirmationKlasses[$params["kind"]], '_doCreate'), - '/transparent_redirect_requests/' . $params['id'] . '/confirm', - array() - ); + return Configuration::gateway()->transparentRedirect()->confirm($queryString); } - /** - * returns the trData string for creating a credit card, - * @param array $params - * @return string - */ public static function createCreditCardData($params) { - Braintree_Util::verifyKeys( - self::$_createCreditCardSignature, - $params - ); - $params["kind"] = Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD; - return self::_data($params); + return Configuration::gateway()->transparentRedirect()->createCreditCardData($params); } - /** - * returns the trData string for creating a customer. - * @param array $params - * @return string - */ public static function createCustomerData($params) { - Braintree_Util::verifyKeys( - self::$_createCustomerSignature, - $params - ); - $params["kind"] = Braintree_TransparentRedirect::CREATE_CUSTOMER; - return self::_data($params); - + return Configuration::gateway()->transparentRedirect()->createCustomerData($params); } public static function url() { - return Braintree_Configuration::merchantUrl() . "/transparent_redirect_requests"; + return Configuration::gateway()->transparentRedirect()->url(); } - /** - * returns the trData string for creating a transaction - * @param array $params - * @return string - */ public static function transactionData($params) { - Braintree_Util::verifyKeys( - self::$_transactionSignature, - $params - ); - $params["kind"] = Braintree_TransparentRedirect::CREATE_TRANSACTION; - $transactionType = isset($params['transaction']['type']) ? - $params['transaction']['type'] : - null; - if ($transactionType != Braintree_Transaction::SALE && $transactionType != Braintree_Transaction::CREDIT) { - throw new InvalidArgumentException( - 'expected transaction[type] of sale or credit, was: ' . - $transactionType - ); - } - - return self::_data($params); + return Configuration::gateway()->transparentRedirect()->transactionData($params); } - /** - * Returns the trData string for updating a credit card. - * - * The paymentMethodToken of the credit card to update is required. - * - * - * $trData = Braintree_TransparentRedirect::updateCreditCardData(array( - * 'redirectUrl' => 'http://example.com/redirect_here', - * 'paymentMethodToken' => 'token123', - * )); - * - * - * @param array $params - * @return string - */ public static function updateCreditCardData($params) { - Braintree_Util::verifyKeys( - self::$_updateCreditCardSignature, - $params - ); - if (!isset($params['paymentMethodToken'])) { - throw new InvalidArgumentException( - 'expected params to contain paymentMethodToken.' - ); - } - $params["kind"] = Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD; - return self::_data($params); + return Configuration::gateway()->transparentRedirect()->updateCreditCardData($params); } - /** - * Returns the trData string for updating a customer. - * - * The customerId of the customer to update is required. - * - * - * $trData = Braintree_TransparentRedirect::updateCustomerData(array( - * 'redirectUrl' => 'http://example.com/redirect_here', - * 'customerId' => 'customer123', - * )); - * - * - * @param array $params - * @return string - */ public static function updateCustomerData($params) { - Braintree_Util::verifyKeys( - self::$_updateCustomerSignature, - $params - ); - if (!isset($params['customerId'])) { - throw new InvalidArgumentException( - 'expected params to contain customerId of customer to update' - ); - } - $params["kind"] = Braintree_TransparentRedirect::UPDATE_CUSTOMER; - return self::_data($params); + return Configuration::gateway()->transparentRedirect()->updateCustomerData($params); } public static function parseAndValidateQueryString($queryString) { - // parse the params into an array - parse_str($queryString, $params); - // remove the hash - $queryStringWithoutHash = null; - if(preg_match('/^(.*)&hash=[a-f0-9]+$/', $queryString, $match)) { - $queryStringWithoutHash = $match[1]; - } - - if($params['http_status'] != '200') { - $message = null; - if(array_key_exists('bt_message', $params)) { - $message = $params['bt_message']; - } - Braintree_Util::throwStatusCodeException($params['http_status'], $message); - } - - // recreate the hash and compare it - if(self::_hash($queryStringWithoutHash) == $params['hash']) { - return $params; - } else { - throw new Braintree_Exception_ForgedQueryString(); - } - } - - - /** - * - * @ignore - */ - private static function _data($params) - { - if (!isset($params['redirectUrl'])) { - throw new InvalidArgumentException( - 'expected params to contain redirectUrl' - ); - } - $params = self::_underscoreKeys($params); - $now = new DateTime('now', new DateTimeZone('UTC')); - $trDataParams = array_merge($params, - array( - 'api_version' => Braintree_Configuration::API_VERSION, - 'public_key' => Braintree_Configuration::publicKey(), - 'time' => $now->format('YmdHis'), - ) - ); - ksort($trDataParams); - $trDataSegment = http_build_query($trDataParams, null, '&'); - $trDataHash = self::_hash($trDataSegment); - return "$trDataHash|$trDataSegment"; - } - - private static function _underscoreKeys($array) - { - foreach($array as $key=>$value) - { - $newKey = Braintree_Util::camelCaseToDelimiter($key, '_'); - unset($array[$key]); - if (is_array($value)) - { - $array[$newKey] = self::_underscoreKeys($value); - } - else - { - $array[$newKey] = $value; - } - } - return $array; - } - - /** - * @ignore - */ - private static function _hash($string) - { - return Braintree_Digest::hexDigest($string); + return Configuration::gateway()->transparentRedirect()->parseAndValidateQueryString($queryString); } - } -Braintree_TransparentRedirect::init(); +class_alias('Braintree\TransparentRedirect', 'Braintree_TransparentRedirect'); diff --git a/lib/Braintree/TransparentRedirectGateway.php b/lib/Braintree/TransparentRedirectGateway.php new file mode 100644 index 0000000..3308af0 --- /dev/null +++ b/lib/Braintree/TransparentRedirectGateway.php @@ -0,0 +1,289 @@ +_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + } + + /** + * + * @ignore + */ + private static $_transparentRedirectKeys = 'redirectUrl'; + private static $_createCustomerSignature; + private static $_updateCustomerSignature; + private static $_transactionSignature; + private static $_createCreditCardSignature; + private static $_updateCreditCardSignature; + + /** + * create signatures for different call types + * @ignore + */ + public static function init() + { + + self::$_createCustomerSignature = [ + self::$_transparentRedirectKeys, + ['customer' => CustomerGateway::createSignature()], + ]; + self::$_updateCustomerSignature = [ + self::$_transparentRedirectKeys, + 'customerId', + ['customer' => CustomerGateway::updateSignature()], + ]; + self::$_transactionSignature = [ + self::$_transparentRedirectKeys, + ['transaction' => TransactionGateway::createSignature()], + ]; + self::$_createCreditCardSignature = [ + self::$_transparentRedirectKeys, + ['creditCard' => CreditCardGateway::createSignature()], + ]; + self::$_updateCreditCardSignature = [ + self::$_transparentRedirectKeys, + 'paymentMethodToken', + ['creditCard' => CreditCardGateway::updateSignature()], + ]; + } + + public function confirm($queryString) + { + $params = TransparentRedirect::parseAndValidateQueryString( + $queryString + ); + $confirmationKlasses = [ + TransparentRedirect::CREATE_TRANSACTION => 'Braintree\TransactionGateway', + TransparentRedirect::CREATE_CUSTOMER => 'Braintree\CustomerGateway', + TransparentRedirect::UPDATE_CUSTOMER => 'Braintree\CustomerGateway', + TransparentRedirect::CREATE_PAYMENT_METHOD => 'Braintree\CreditCardGateway', + TransparentRedirect::UPDATE_PAYMENT_METHOD => 'Braintree\CreditCardGateway', + ]; + $confirmationGateway = new $confirmationKlasses[$params["kind"]]($this->_gateway); + return $confirmationGateway->_doCreate('/transparent_redirect_requests/' . $params['id'] . '/confirm', []); + } + + /** + * returns the trData string for creating a credit card, + * @param array $params + * @return string + */ + public function createCreditCardData($params) + { + Util::verifyKeys( + self::$_createCreditCardSignature, + $params + ); + $params["kind"] = TransparentRedirect::CREATE_PAYMENT_METHOD; + return $this->_data($params); + } + + /** + * returns the trData string for creating a customer. + * @param array $params + * @return string + */ + public function createCustomerData($params) + { + Util::verifyKeys( + self::$_createCustomerSignature, + $params + ); + $params["kind"] = TransparentRedirect::CREATE_CUSTOMER; + return $this->_data($params); + + } + + public function url() + { + return $this->_config->baseUrl() . $this->_config->merchantPath() . '/transparent_redirect_requests'; + } + + /** + * returns the trData string for creating a transaction + * @param array $params + * @return string + */ + public function transactionData($params) + { + Util::verifyKeys( + self::$_transactionSignature, + $params + ); + $params["kind"] = TransparentRedirect::CREATE_TRANSACTION; + $transactionType = isset($params['transaction']['type']) ? + $params['transaction']['type'] : + null; + if ($transactionType != Transaction::SALE && $transactionType != Transaction::CREDIT) { + throw new InvalidArgumentException( + 'expected transaction[type] of sale or credit, was: ' . + $transactionType + ); + } + + return $this->_data($params); + } + + /** + * Returns the trData string for updating a credit card. + * + * The paymentMethodToken of the credit card to update is required. + * + * + * $trData = TransparentRedirect::updateCreditCardData(array( + * 'redirectUrl' => 'http://example.com/redirect_here', + * 'paymentMethodToken' => 'token123', + * )); + * + * + * @param array $params + * @return string + */ + public function updateCreditCardData($params) + { + Util::verifyKeys( + self::$_updateCreditCardSignature, + $params + ); + if (!isset($params['paymentMethodToken'])) { + throw new InvalidArgumentException( + 'expected params to contain paymentMethodToken.' + ); + } + $params["kind"] = TransparentRedirect::UPDATE_PAYMENT_METHOD; + return $this->_data($params); + } + + /** + * Returns the trData string for updating a customer. + * + * The customerId of the customer to update is required. + * + * + * $trData = TransparentRedirect::updateCustomerData(array( + * 'redirectUrl' => 'http://example.com/redirect_here', + * 'customerId' => 'customer123', + * )); + * + * + * @param array $params + * @return string + */ + public function updateCustomerData($params) + { + Util::verifyKeys( + self::$_updateCustomerSignature, + $params + ); + if (!isset($params['customerId'])) { + throw new InvalidArgumentException( + 'expected params to contain customerId of customer to update' + ); + } + $params["kind"] = TransparentRedirect::UPDATE_CUSTOMER; + return $this->_data($params); + } + + public function parseAndValidateQueryString($queryString) + { + // parse the params into an array + parse_str($queryString, $params); + // remove the hash + $queryStringWithoutHash = null; + if (preg_match('/^(.*)&hash=[a-f0-9]+$/', $queryString, $match)) { + $queryStringWithoutHash = $match[1]; + } + + if($params['http_status'] != '200') { + $message = null; + if(array_key_exists('bt_message', $params)) { + $message = $params['bt_message']; + } + Util::throwStatusCodeException(isset($params['http_status']) ? $params['http_status'] : null, $message); + } + + // recreate the hash and compare it + if ($this->_hash($queryStringWithoutHash) == $params['hash']) { + return $params; + } else { + throw new Exception\ForgedQueryString(); + } + } + + + /** + * + * @ignore + */ + private function _data($params) + { + if (!isset($params['redirectUrl'])) { + throw new InvalidArgumentException( + 'expected params to contain redirectUrl' + ); + } + $params = $this->_underscoreKeys($params); + $now = new DateTime('now', new DateTimeZone('UTC')); + $trDataParams = array_merge($params, + [ + 'api_version' => Configuration::API_VERSION, + 'public_key' => $this->_config->publicKey(), + 'time' => $now->format('YmdHis'), + ] + ); + ksort($trDataParams); + $urlEncodedData = http_build_query($trDataParams, null, "&"); + $signatureService = new SignatureService( + $this->_config->privateKey(), + "Braintree\Digest::hexDigestSha1" + ); + return $signatureService->sign($urlEncodedData); + } + + private function _underscoreKeys($array) + { + foreach($array as $key=>$value) + { + $newKey = Util::camelCaseToDelimiter($key, '_'); + unset($array[$key]); + if (is_array($value)) + { + $array[$newKey] = $this->_underscoreKeys($value); + } + else + { + $array[$newKey] = $value; + } + } + return $array; + } + + /** + * @ignore + */ + private function _hash($string) + { + return Digest::hexDigestSha1($this->_config->privateKey(), $string); + } +} +TransparentRedirectGateway::init(); +class_alias('Braintree\TransparentRedirectGateway', 'Braintree_TransparentRedirectGateway'); diff --git a/lib/Braintree/UnknownPaymentMethod.php b/lib/Braintree/UnknownPaymentMethod.php new file mode 100644 index 0000000..74e7289 --- /dev/null +++ b/lib/Braintree/UnknownPaymentMethod.php @@ -0,0 +1,69 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $token + * @property-read string $imageUrl + */ +class UnknownPaymentMethod extends Base +{ + + + /** + * factory method: returns an instance of UnknownPaymentMethod + * to the requesting method, with populated properties + * + * @ignore + * @return UnknownPaymentMethod + */ + public static function factory($attributes) + { + $instance = new self(); + $values = array_values($attributes); + $instance->_initialize(array_shift($values)); + return $instance; + } + + /* instance methods */ + + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $unknownPaymentMethodAttribs array of unknownPaymentMethod data + * @return void + */ + protected function _initialize($unknownPaymentMethodAttribs) + { + // set the attributes + $this->imageUrl = 'https://assets.braintreegateway.com/payment_method_logo/unknown.png'; + $this->_attributes = $unknownPaymentMethodAttribs; + } + +} +class_alias('Braintree\UnknownPaymentMethod', 'Braintree_UnknownPaymentMethod'); diff --git a/lib/Braintree/UsBankAccount.php b/lib/Braintree/UsBankAccount.php new file mode 100644 index 0000000..bf86fbe --- /dev/null +++ b/lib/Braintree/UsBankAccount.php @@ -0,0 +1,117 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $customerId + * @property-read string $email + * @property-read string $token + * @property-read string $imageUrl + * @property-read string $routingNumber + * @property-read string $accountType + * @property-read string $accountHolderName + * @property-read string $last4 + * @property-read string $bankName + * @property-read string $achMandate + * @property-read string $default + * @property-read boolean $verified + */ +class UsBankAccount extends Base +{ + /** + * factory method: returns an instance of UsBankAccount + * to the requesting method, with populated properties + * + * @ignore + * @return UsBankAccount + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $usBankAccountAttribs array of usBankAccount data + * @return void + */ + protected function _initialize($usBankAccountAttribs) + { + // set the attributes + $this->_attributes = $usBankAccountAttribs; + + $achMandate = isset($usBankAccountAttribs['achMandate']) ? + AchMandate::factory($usBankAccountAttribs['achMandate']) : + null; + $this->_set('achMandate', $achMandate); + + if (isset($usBankAccountAttribs['verifications'])) { + $verification_records = $usBankAccountAttribs['verifications']; + + $verifications = array(); + for ($i = 0; $i < count($verification_records); $i++) { + $verifications[$i] = UsBankAccountVerification::factory($verification_records[$i]); + } + $this->_set('verifications', $verifications); + } else { + $this->_set('verifications', null); + } + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } + + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + // static methods redirecting to gateway + + public static function find($token) + { + return Configuration::gateway()->usBankAccount()->find($token); + } + + public static function sale($token, $transactionAttribs) + { + $transactionAttribs['options'] = [ + 'submitForSettlement' => true + ]; + return Configuration::gateway()->usBankAccount()->sale($token, $transactionAttribs); + } +} +class_alias('Braintree\UsBankAccount', 'Braintree_UsBankAccount'); diff --git a/lib/Braintree/UsBankAccountGateway.php b/lib/Braintree/UsBankAccountGateway.php new file mode 100644 index 0000000..6e3393c --- /dev/null +++ b/lib/Braintree/UsBankAccountGateway.php @@ -0,0 +1,106 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class UsBankAccountGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + + /** + * find a usBankAccount by token + * + * @access public + * @param string $token paypal accountunique id + * @return UsBankAccount + * @throws Exception\NotFound + */ + public function find($token) + { + try { + $path = $this->_config->merchantPath() . '/payment_methods/us_bank_account/' . $token; + $response = $this->_http->get($path); + return UsBankAccount::factory($response['usBankAccount']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'US bank account with token ' . $token . ' not found' + ); + } + + } + + /** + * create a new sale for the current UsBank account + * + * @param string $token + * @param array $transactionAttribs + * @return Result\Successful|Result\Error + * @see Transaction::sale() + */ + public function sale($token, $transactionAttribs) + { + return Transaction::sale( + array_merge( + $transactionAttribs, + ['paymentMethodToken' => $token] + ) + ); + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new UsBankAccount object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['usBankAccount'])) { + // return a populated instance of UsBankAccount + return new Result\Successful( + UsBankAccount::factory($response['usBankAccount']) + ); + } else if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else { + throw new Exception\Unexpected( + 'Expected US bank account or apiErrorResponse' + ); + } + } +} +class_alias('Braintree\UsBankAccountGateway', 'Braintree_UsBankAccountGateway'); diff --git a/lib/Braintree/UsBankAccountVerification.php b/lib/Braintree/UsBankAccountVerification.php new file mode 100644 index 0000000..a062a55 --- /dev/null +++ b/lib/Braintree/UsBankAccountVerification.php @@ -0,0 +1,102 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + */ +class UsBankAccountVerification extends Result\UsBankAccountVerification +{ + /** + * factory method: returns an instance of UsBankAccountVerification + * to the requesting method, with populated properties + * + * @ignore + * @return UsBankAccountVerification + */ + public static function factory($attributes) + { + $instance = new self($attributes); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $usBankAccountVerificationAttribs array of usBankAccountVerification data + * @return void + */ + protected function _initialize($usBankAccountVerificationAttribs) + { + // set the attributes + $this->_attributes = $usBankAccountVerificationAttribs; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; + } + + + // static methods redirecting to gateway + + /** + * finds a US bank account verification + * + * @access public + * @param string $token unique id + * @return UsBankAccountVerification + */ + public static function find($token) + { + return Configuration::gateway()->usBankAccountVerification()->find($token); + } + + /** + * Returns a ResourceCollection of US bank account verifications matching the search query. + * + * @access public + * @param mixed $query search query + * @return ResourceCollection + */ + public static function search($query) + { + return Configuration::gateway()->usBankAccountVerification()->search($query); + } + + /** + * Returns a ResourceCollection of US bank account verifications matching the search query. + * + * @access public + * @param string $token unique id + * @param array $amounts micro transfer amounts + * @return ResourceCollection + */ + public static function confirmMicroTransferAmounts($token, $amounts) + { + return Configuration::gateway()->usBankAccountVerification()->confirmMicroTransferAmounts($token, $amounts); + } +} +class_alias('Braintree\UsBankAccountVerification', 'Braintree_UsBankAccountVerification'); diff --git a/lib/Braintree/UsBankAccountVerificationGateway.php b/lib/Braintree/UsBankAccountVerificationGateway.php new file mode 100644 index 0000000..31397ad --- /dev/null +++ b/lib/Braintree/UsBankAccountVerificationGateway.php @@ -0,0 +1,129 @@ +== More information == + * + * + * @package Braintree + * @category Resources + */ +class UsBankAccountVerificationGateway +{ + private $_gateway; + private $_config; + private $_http; + + public function __construct($gateway) + { + $this->_gateway = $gateway; + $this->_config = $gateway->config; + $this->_config->assertHasAccessTokenOrKeys(); + $this->_http = new Http($gateway->config); + } + + /** + * find a usBankAccountVerification by token + * + * @access public + * @param string $token unique id + * @return UsBankAccountVerification + * @throws Exception\NotFound + */ + public function find($token) + { + try { + $path = $this->_config->merchantPath() . '/us_bank_account_verifications/' . $token; + $response = $this->_http->get($path); + return UsBankAccountVerification::factory($response['usBankAccountVerification']); + } catch (Exception\NotFound $e) { + throw new Exception\NotFound( + 'US bank account with token ' . $token . ' not found' + ); + } + } + + public function search($query) + { + $criteria = []; + foreach ($query as $term) { + $criteria[$term->name] = $term->toparam(); + } + + $path = $this->_config->merchantPath() . '/us_bank_account_verifications/advanced_search_ids'; + $response = $this->_http->post($path, ['search' => $criteria]); + $pager = [ + 'object' => $this, + 'method' => 'fetch', + 'methodArgs' => [$query] + ]; + + return new ResourceCollection($response, $pager); + } + + /** + * complete micro transfer verification by confirming the transfer amounts + * + * @access public + * @param string $token unique id + * @param array $amounts amounts deposited in micro transfer + * @return UsBankAccountVerification + * @throws Exception\Unexpected + */ + public function confirmMicroTransferAmounts($token, $amounts) + { + try { + $path = $this->_config->merchantPath() . '/us_bank_account_verifications/' . $token . '/confirm_micro_transfer_amounts'; + $response = $this->_http->put($path, [ + "us_bank_account_verification" => ["deposit_amounts" => $amounts] + ]); + return $this->_verifyGatewayResponse($response); + } catch (Exception\Unexpected $e) { + throw new Exception\Unexpected( + 'Unexpected exception.' + ); + } + } + + /** + * generic method for validating incoming gateway responses + * + * creates a new UsBankAccountVerification object and encapsulates + * it inside a Result\Successful object, or + * encapsulates a Errors object inside a Result\Error + * alternatively, throws an Unexpected exception if the response is invalid. + * + * @ignore + * @param array $response gateway response values + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + private function _verifyGatewayResponse($response) + { + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else if (isset($response['usBankAccountVerification'])) { + // return a populated instance of UsBankAccountVerification + return new Result\Successful( + UsBankAccountVerification::factory($response['usBankAccountVerification']) + ); + } else { + throw new Exception\Unexpected( + 'Expected US bank account or apiErrorResponse' + ); + } + } +} + +class_alias('Braintree\UsBankAccountVerificationGateway', 'Braintree_UsBankAccountVerificationGateway'); diff --git a/lib/Braintree/UsBankAccountVerificationSearch.php b/lib/Braintree/UsBankAccountVerificationSearch.php new file mode 100644 index 0000000..a6336dc --- /dev/null +++ b/lib/Braintree/UsBankAccountVerificationSearch.php @@ -0,0 +1,64 @@ +success) { + return $resultObj->$resultObjName; + } else { + throw new Exception\ValidationsFailed(); + } + } + + /** + * removes the header from a classname * - * @param string $name Braintree_ClassName - * @return camelCased classname minus Braintree_ header + * @param string $name ClassName + * @return camelCased classname minus header */ public static function cleanClassName($name) { - $classNamesToResponseKeys = array( - 'CreditCard' => 'creditCard', - 'Customer' => 'customer', - 'Subscription' => 'subscription', - 'Transaction' => 'transaction', - 'CreditCardVerification' => 'verification', - 'AddOn' => 'addOn', - 'Discount' => 'discount', - 'Plan' => 'plan', - 'Address' => 'address', - 'SettlementBatchSummary' => 'settlementBatchSummary', - 'MerchantAccount' => 'merchantAccount' - ); + $classNamesToResponseKeys = [ + 'Braintree\CreditCard' => 'creditCard', + 'Braintree_CreditCard' => 'creditCard', + 'Braintree\CreditCardGateway' => 'creditCard', + 'Braintree_CreditCardGateway' => 'creditCard', + 'Braintree\Customer' => 'customer', + 'Braintree_Customer' => 'customer', + 'Braintree\CustomerGateway' => 'customer', + 'Braintree_CustomerGateway' => 'customer', + 'Braintree\Subscription' => 'subscription', + 'Braintree_Subscription' => 'subscription', + 'Braintree\SubscriptionGateway' => 'subscription', + 'Braintree_SubscriptionGateway' => 'subscription', + 'Braintree\Transaction' => 'transaction', + 'Braintree_Transaction' => 'transaction', + 'Braintree\TransactionGateway' => 'transaction', + 'Braintree_TransactionGateway' => 'transaction', + 'Braintree\CreditCardVerification' => 'verification', + 'Braintree_CreditCardVerification' => 'verification', + 'Braintree\CreditCardVerificationGateway' => 'verification', + 'Braintree_CreditCardVerificationGateway' => 'verification', + 'Braintree\AddOn' => 'addOn', + 'Braintree_AddOn' => 'addOn', + 'Braintree\AddOnGateway' => 'addOn', + 'Braintree_AddOnGateway' => 'addOn', + 'Braintree\Discount' => 'discount', + 'Braintree_Discount' => 'discount', + 'Braintree\DiscountGateway' => 'discount', + 'Braintree_DiscountGateway' => 'discount', + 'Braintree\Dispute' => 'dispute', + 'Braintree_Dispute' => 'dispute', + 'Braintree\Dispute\EvidenceDetails' => 'evidence', + 'Braintree_Dispute_EvidenceDetails' => 'evidence', + 'Braintree\DocumentUpload' => 'documentUpload', + 'Braintree_DocumentUpload' => 'doumentUpload', + 'Braintree\Plan' => 'plan', + 'Braintree_Plan' => 'plan', + 'Braintree\PlanGateway' => 'plan', + 'Braintree_PlanGateway' => 'plan', + 'Braintree\Address' => 'address', + 'Braintree_Address' => 'address', + 'Braintree\AddressGateway' => 'address', + 'Braintree_AddressGateway' => 'address', + 'Braintree\SettlementBatchSummary' => 'settlementBatchSummary', + 'Braintree_SettlementBatchSummary' => 'settlementBatchSummary', + 'Braintree\SettlementBatchSummaryGateway' => 'settlementBatchSummary', + 'Braintree_SettlementBatchSummaryGateway' => 'settlementBatchSummary', + 'Braintree\Merchant' => 'merchant', + 'Braintree_Merchant' => 'merchant', + 'Braintree\MerchantGateway' => 'merchant', + 'Braintree_MerchantGateway' => 'merchant', + 'Braintree\MerchantAccount' => 'merchantAccount', + 'Braintree_MerchantAccount' => 'merchantAccount', + 'Braintree\MerchantAccountGateway' => 'merchantAccount', + 'Braintree_MerchantAccountGateway' => 'merchantAccount', + 'Braintree\OAuthCredentials' => 'credentials', + 'Braintree_OAuthCredentials' => 'credentials', + 'Braintree\OAuthResult' => 'result', + 'Braintree_OAuthResult' => 'result', + 'Braintree\PayPalAccount' => 'paypalAccount', + 'Braintree_PayPalAccount' => 'paypalAccount', + 'Braintree\PayPalAccountGateway' => 'paypalAccount', + 'Braintree_PayPalAccountGateway' => 'paypalAccount', + 'Braintree\UsBankAccountVerification' => 'usBankAccountVerification', + 'Braintree_UsBankAccountVerification' => 'usBankAccountVerification', + ]; - $name = str_replace('Braintree_', '', $name); return $classNamesToResponseKeys[$name]; } /** * * @param string $name className - * @return string Braintree_ClassName + * @return string ClassName */ public static function buildClassName($name) { - $responseKeysToClassNames = array( - 'creditCard' => 'CreditCard', - 'customer' => 'Customer', - 'subscription' => 'Subscription', - 'transaction' => 'Transaction', - 'verification' => 'CreditCardVerification', - 'addOn' => 'AddOn', - 'discount' => 'Discount', - 'plan' => 'Plan', - 'address' => 'Address', - 'settlementBatchSummary' => 'SettlementBatchSummary', - 'merchantAccount' => 'MerchantAccount' - ); + $responseKeysToClassNames = [ + 'creditCard' => 'Braintree\CreditCard', + 'customer' => 'Braintree\Customer', + 'dispute' => 'Braintree\Dispute', + 'documentUpload' => 'Braintree\DocumentUpload', + 'subscription' => 'Braintree\Subscription', + 'transaction' => 'Braintree\Transaction', + 'verification' => 'Braintree\CreditCardVerification', + 'addOn' => 'Braintree\AddOn', + 'discount' => 'Braintree\Discount', + 'plan' => 'Braintree\Plan', + 'address' => 'Braintree\Address', + 'settlementBatchSummary' => 'Braintree\SettlementBatchSummary', + 'merchantAccount' => 'Braintree\MerchantAccount', + ]; - return 'Braintree_' . $responseKeysToClassNames[$name]; + return (string) $responseKeysToClassNames[$name]; } /** @@ -134,16 +254,16 @@ public static function buildClassName($name) * * @access public * @param string $string + * @param null|string $delimiter * @return string modified string */ public static function delimiterToCamelCase($string, $delimiter = '[\-\_]') { - // php doesn't garbage collect functions created by create_function() - // so use a static variable to avoid adding a new function to memory - // every time this function is called. static $callback = null; if ($callback === null) { - $callback = create_function('$matches', 'return strtoupper($matches[1]);'); + $callback = function ($matches) { + return strtoupper($matches[1]); + }; } return preg_replace_callback('/' . $delimiter . '(\w)/', $callback, $string); @@ -166,20 +286,60 @@ public static function delimiterToUnderscore($string) * find capitals and convert to delimiter + lowercase * * @access public - * @param var $string - * @return var modified string + * @param string $string + * @param null|string $delimiter + * @return string modified string */ public static function camelCaseToDelimiter($string, $delimiter = '-') { - // php doesn't garbage collect functions created by create_function() - // so use a static variable to avoid adding a new function to memory - // every time this function is called. - static $callbacks = array(); - if (!isset($callbacks[$delimiter])) { - $callbacks[$delimiter] = create_function('$matches', "return '$delimiter' . strtolower(\$matches[1]);"); + return strtolower(preg_replace('/([A-Z])/', "$delimiter\\1", $string)); + } + + public static function delimiterToCamelCaseArray($array, $delimiter = '[\-\_]') + { + $converted = []; + foreach ($array as $key => $value) { + if (is_string($key)) { + $key = self::delimiterToCamelCase($key, $delimiter); + } + + if (is_array($value)) { + // Make an exception for custom fields, which must be underscore (can't be + // camelCase). + if ($key === 'customFields') { + $value = self::delimiterToUnderscoreArray($value); + } else { + $value = self::delimiterToCamelCaseArray($value, $delimiter); + } + } + $converted[$key] = $value; + } + return $converted; + } + + public static function camelCaseToDelimiterArray($array, $delimiter = '-') + { + $converted = []; + foreach ($array as $key => $value) { + if (is_string($key)) { + $key = self::camelCaseToDelimiter($key, $delimiter); + } + if (is_array($value)) { + $value = self::camelCaseToDelimiterArray($value, $delimiter); + } + $converted[$key] = $value; } + return $converted; + } - return preg_replace_callback('/([A-Z])/', $callbacks[$delimiter], $string); + public static function delimiterToUnderscoreArray($array) + { + $converted = []; + foreach ($array as $key => $value) { + $key = self::delimiterToUnderscore($key); + $converted[$key] = $value; + } + return $converted; } /** @@ -187,24 +347,27 @@ public static function camelCaseToDelimiter($string, $delimiter = '-') * @param array $array associative array to implode * @param string $separator (optional, defaults to =) * @param string $glue (optional, defaults to ', ') + * @return bool */ public static function implodeAssociativeArray($array, $separator = '=', $glue = ', ') { // build a new array with joined keys and values $tmpArray = null; foreach ($array AS $key => $value) { - $tmpArray[] = $key . $separator . $value; - + if ($value instanceof DateTime) { + $value = $value->format('r'); + } + $tmpArray[] = $key . $separator . $value; } // implode and return the new array return (is_array($tmpArray)) ? implode($glue, $tmpArray) : false; } public static function attributesToString($attributes) { - $printableAttribs = array(); + $printableAttribs = []; foreach ($attributes AS $key => $value) { if (is_array($value)) { - $pAttrib = Braintree_Util::attributesToString($value); + $pAttrib = self::attributesToString($value); } else if ($value instanceof DateTime) { $pAttrib = $value->format(DateTime::RFC850); } else { @@ -212,7 +375,7 @@ public static function attributesToString($attributes) { } $printableAttribs[$key] = sprintf('%s', $pAttrib); } - return Braintree_Util::implodeAssociativeArray($printableAttribs); + return self::implodeAssociativeArray($printableAttribs); } /** @@ -234,7 +397,7 @@ public static function verifyKeys($signature, $attributes) if(!empty($invalidKeys)) { asort($invalidKeys); $sortedList = join(', ', $invalidKeys); - throw new InvalidArgumentException('invalid keys: '. $sortedList); + throw new InvalidArgumentException('invalid keys: ' . $sortedList); } } /** @@ -245,7 +408,7 @@ public static function verifyKeys($signature, $attributes) */ private static function _flattenArray($keys, $namespace = null) { - $flattenedArray = array(); + $flattenedArray = []; foreach($keys AS $key) { if(is_array($key)) { $theKeys = array_keys($key); @@ -264,7 +427,7 @@ private static function _flattenArray($keys, $namespace = null) private static function _flattenUserKeys($keys, $namespace = null) { - $flattenedArray = array(); + $flattenedArray = []; foreach($keys AS $key => $value) { $fullKey = empty($namespace) ? $key : $namespace; @@ -306,3 +469,4 @@ private static function _removeWildcardKeys($validKeys, $invalidKeys) return $invalidKeys; } } +class_alias('Braintree\Util', 'Braintree_Util'); diff --git a/lib/Braintree/VenmoAccount.php b/lib/Braintree/VenmoAccount.php new file mode 100644 index 0000000..735e081 --- /dev/null +++ b/lib/Braintree/VenmoAccount.php @@ -0,0 +1,74 @@ +== More information == + * + * See {@link https://developers.braintreepayments.com/javascript+php}
+ * + * @package Braintree + * @category Resources + * + * @property-read string $createdAt + * @property-read string $default + * @property-read string $updatedAt + * @property-read string $customerId + * @property-read string $sourceDescription + * @property-read string $token + * @property-read string $imageUrl + * @property-read string $username + * @property-read string $venmoUserId + */ +class VenmoAccount extends Base +{ + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * factory method: returns an instance of VenmoAccount + * to the requesting method, with populated properties + * + * @ignore + * @return VenmoAccount + */ + public static function factory($attributes) + { + + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $venmoAccountAttribs array of Venmo account properties + * @return void + */ + protected function _initialize($venmoAccountAttribs) + { + $this->_attributes = $venmoAccountAttribs; + + $subscriptionArray = array(); + if (isset($venmoAccountAttribs['subscriptions'])) { + foreach ($venmoAccountAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + } +} +class_alias('Braintree\VenmoAccount', 'Braintree_VenmoAccount'); diff --git a/lib/Braintree/Version.php b/lib/Braintree/Version.php index 5a04005..2616523 100644 --- a/lib/Braintree/Version.php +++ b/lib/Braintree/Version.php @@ -1,23 +1,17 @@ == More information == + * + * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} + * + * @package Braintree + * @category Resources + * + * @property-read string $billingAddress + * @property-read string $bin + * @property-read string $callId + * @property-read string $cardType + * @property-read string $cardholderName + * @property-read string $commercial + * @property-read string $countryOfIssuance + * @property-read string $createdAt + * @property-read string $customerId + * @property-read string $customerLocation + * @property-read string $debit + * @property-read string $default + * @property-read string $durbinRegulated + * @property-read string $expirationDate + * @property-read string $expirationMonth + * @property-read string $expirationYear + * @property-read string $expired + * @property-read string $healthcare + * @property-read string $imageUrl + * @property-read string $issuingBank + * @property-read string $last4 + * @property-read string $maskedNumber + * @property-read string $payroll + * @property-read string $prepaid + * @property-read string $productId + * @property-read string $subscriptions + * @property-read string $token + * @property-read string $uniqueNumberIdentifier + * @property-read string $updatedAt + */ +class VisaCheckoutCard extends Base +{ + /* instance methods */ + /** + * returns false if default is null or false + * + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * checks whether the card is expired based on the current date + * + * @return boolean + */ + public function isExpired() + { + return $this->expired; + } + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $creditCardAttribs array of creditcard data + * @return void + */ + protected function _initialize($creditCardAttribs) + { + // set the attributes + $this->_attributes = $creditCardAttribs; + + // map each address into its own object + $billingAddress = isset($creditCardAttribs['billingAddress']) ? + Address::factory($creditCardAttribs['billingAddress']) : + null; + + $subscriptionArray = []; + if (isset($creditCardAttribs['subscriptions'])) { + foreach ($creditCardAttribs['subscriptions'] AS $subscription) { + $subscriptionArray[] = Subscription::factory($subscription); + } + } + + $this->_set('subscriptions', $subscriptionArray); + $this->_set('billingAddress', $billingAddress); + $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); + $this->_set('maskedNumber', $this->bin . '******' . $this->last4); + + if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { + $verifications = $creditCardAttribs['verifications']; + usort($verifications, [$this, '_compareCreatedAtOnVerifications']); + + $this->_set('verification', CreditCardVerification::factory($verifications[0])); + } + } + + private function _compareCreatedAtOnVerifications($verificationAttrib1, $verificationAttrib2) + { + return ($verificationAttrib2['createdAt'] < $verificationAttrib1['createdAt']) ? -1 : 1; + } + + /** + * returns false if comparing object is not a VisaCheckoutCard, + * or is a VisaCheckoutCard with a different id + * + * @param object $otherVisaCheckoutCard customer to compare against + * @return boolean + */ + public function isEqual($otherVisaCheckoutCard) + { + return !($otherVisaCheckoutCard instanceof self) ? false : $this->token === $otherVisaCheckoutCard->token; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) .']'; + } + + /** + * factory method: returns an instance of VisaCheckoutCard + * to the requesting method, with populated properties + * + * @ignore + * @return VisaCheckoutCard + */ + public static function factory($attributes) + { + $defaultAttributes = [ + 'bin' => '', + 'expirationMonth' => '', + 'expirationYear' => '', + 'last4' => '', + ]; + + $instance = new self(); + $instance->_initialize(array_merge($defaultAttributes, $attributes)); + return $instance; + } +} +class_alias('Braintree\VisaCheckoutCard', 'Braintree_VisaCheckoutCard'); diff --git a/lib/Braintree/WebhookNotification.php b/lib/Braintree/WebhookNotification.php index 873211d..05d2cb6 100644 --- a/lib/Braintree/WebhookNotification.php +++ b/lib/Braintree/WebhookNotification.php @@ -1,5 +1,7 @@ webhookNotification()->parse($signature, $payload); } - public static function verify($challenge) - { - $publicKey = Braintree_Configuration::publicKey(); - $digest = Braintree_Digest::hexDigest($challenge); - return "{$publicKey}|{$digest}"; + public static function verify($challenge) { + return Configuration::gateway()->webhookNotification()->verify($challenge); } public static function factory($attributes) @@ -40,34 +48,14 @@ public static function factory($attributes) return $instance; } - private static function _matchingSignature($signaturePairs) - { - foreach ($signaturePairs as $pair) - { - $components = preg_split("/\|/", $pair); - if ($components[0] == Braintree_Configuration::publicKey()) { - return $components[1]; - } - } - - return null; - } - - private static function _validateSignature($signature, $payload) - { - $signaturePairs = preg_split("/&/", $signature); - $matchingSignature = self::_matchingSignature($signaturePairs); - - $payloadSignature = Braintree_Digest::hexDigest($payload); - if (!Braintree_Digest::secureCompare($matchingSignature, $payloadSignature)) { - throw new Braintree_Exception_InvalidSignature("webhook notification signature invalid"); - } - } - protected function _initialize($attributes) { $this->_attributes = $attributes; + if (!isset($attributes['sourceMerchantId'])) { + $this->_set('sourceMerchantId', null); + } + if (isset($attributes['subject']['apiErrorResponse'])) { $wrapperNode = $attributes['subject']['apiErrorResponse']; } else { @@ -75,28 +63,61 @@ protected function _initialize($attributes) } if (isset($wrapperNode['subscription'])) { - $this->_set('subscription', Braintree_Subscription::factory($attributes['subject']['subscription'])); + $this->_set('subscription', Subscription::factory($attributes['subject']['subscription'])); } if (isset($wrapperNode['merchantAccount'])) { - $this->_set('merchantAccount', Braintree_MerchantAccount::factory($wrapperNode['merchantAccount'])); + $this->_set('merchantAccount', MerchantAccount::factory($wrapperNode['merchantAccount'])); } if (isset($wrapperNode['transaction'])) { - $this->_set('transaction', Braintree_Transaction::factory($wrapperNode['transaction'])); + $this->_set('transaction', Transaction::factory($wrapperNode['transaction'])); } if (isset($wrapperNode['disbursement'])) { - $this->_set('disbursement', Braintree_Disbursement::factory($wrapperNode['disbursement'])); + $this->_set('disbursement', Disbursement::factory($wrapperNode['disbursement'])); } if (isset($wrapperNode['partnerMerchant'])) { - $this->_set('partnerMerchant', Braintree_PartnerMerchant::factory($wrapperNode['partnerMerchant'])); + $this->_set('partnerMerchant', PartnerMerchant::factory($wrapperNode['partnerMerchant'])); + } + + if (isset($wrapperNode['oauthApplicationRevocation'])) { + $this->_set('oauthAccessRevocation', OAuthAccessRevocation::factory($wrapperNode['oauthApplicationRevocation'])); + } + + if (isset($wrapperNode['connectedMerchantStatusTransitioned'])) { + $this->_set('connectedMerchantStatusTransitioned', ConnectedMerchantStatusTransitioned::factory($wrapperNode['connectedMerchantStatusTransitioned'])); + } + + if (isset($wrapperNode['connectedMerchantPaypalStatusChanged'])) { + $this->_set('connectedMerchantPayPalStatusChanged', ConnectedMerchantPayPalStatusChanged::factory($wrapperNode['connectedMerchantPaypalStatusChanged'])); + } + + if (isset($wrapperNode['dispute'])) { + $this->_set('dispute', Dispute::factory($wrapperNode['dispute'])); + } + + if (isset($wrapperNode['accountUpdaterDailyReport'])) { + $this->_set('accountUpdaterDailyReport', AccountUpdaterDailyReport::factory($wrapperNode['accountUpdaterDailyReport'])); + } + + if (isset($wrapperNode['idealPayment'])) { + $this->_set('idealPayment', IdealPayment::factory($wrapperNode['idealPayment'])); + } + + if (isset($wrapperNode['grantedPaymentInstrumentUpdate'])) { + $this->_set('grantedPaymentInstrumentUpdate', GrantedPaymentInstrumentUpdate::factory($wrapperNode['grantedPaymentInstrumentUpdate'])); + } + + if (isset($wrapperNode['localPayment'])) { + $this->_set('localPaymentCompleted', LocalPaymentCompleted::factory($wrapperNode['localPayment'])); } if (isset($wrapperNode['errors'])) { - $this->_set('errors', new Braintree_Error_ValidationErrorCollection($wrapperNode['errors'])); + $this->_set('errors', new Error\ValidationErrorCollection($wrapperNode['errors'])); $this->_set('message', $wrapperNode['message']); } } } +class_alias('Braintree\WebhookNotification', 'Braintree_WebhookNotification'); diff --git a/lib/Braintree/WebhookNotificationGateway.php b/lib/Braintree/WebhookNotificationGateway.php new file mode 100644 index 0000000..17ef2bb --- /dev/null +++ b/lib/Braintree/WebhookNotificationGateway.php @@ -0,0 +1,77 @@ +config = $gateway->config; + $this->config->assertHasAccessTokenOrKeys(); + } + + public function parse($signature, $payload) + { + if (is_null($signature)) { + throw new Exception\InvalidSignature("signature cannot be null"); + } + + if (is_null($payload)) { + throw new Exception\InvalidSignature("payload cannot be null"); + } + + if (preg_match("/[^A-Za-z0-9+=\/\n]/", $payload) === 1) { + throw new Exception\InvalidSignature("payload contains illegal characters"); + } + + self::_validateSignature($signature, $payload); + + $xml = base64_decode($payload); + $attributes = Xml::buildArrayFromXml($xml); + return WebhookNotification::factory($attributes['notification']); + } + + public function verify($challenge) + { + if (!preg_match('/^[a-f0-9]{20,32}$/', $challenge)) { + throw new Exception\InvalidChallenge("challenge contains non-hex characters"); + } + $publicKey = $this->config->getPublicKey(); + $digest = Digest::hexDigestSha1($this->config->getPrivateKey(), $challenge); + return "{$publicKey}|{$digest}"; + } + + private function _payloadMatches($signature, $payload) + { + $payloadSignature = Digest::hexDigestSha1($this->config->getPrivateKey(), $payload); + return Digest::secureCompare($signature, $payloadSignature); + } + + private function _validateSignature($signatureString, $payload) + { + $signaturePairs = preg_split("/&/", $signatureString); + $signature = self::_matchingSignature($signaturePairs); + if (!$signature) { + throw new Exception\InvalidSignature("no matching public key"); + } + + if (!(self::_payloadMatches($signature, $payload) || self::_payloadMatches($signature, $payload . "\n"))) { + throw new Exception\InvalidSignature("signature does not match payload - one has been modified"); + } + } + + private function _matchingSignature($signaturePairs) + { + foreach ($signaturePairs as $pair) + { + $components = preg_split("/\|/", $pair); + if ($components[0] == $this->config->getPublicKey()) { + return $components[1]; + } + } + + return null; + } +} + +class_alias('Braintree\WebhookNotificationGateway', 'Braintree_WebhookNotificationGateway'); diff --git a/lib/Braintree/WebhookTesting.php b/lib/Braintree/WebhookTesting.php index f8d74da..350591c 100644 --- a/lib/Braintree/WebhookTesting.php +++ b/lib/Braintree/WebhookTesting.php @@ -1,217 +1,11 @@ $signature, - 'payload' => $payload - ); - } - - private static function _sampleXml($kind, $id) - { - switch ($kind) { - case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED: - $subjectXml = self::_merchantAccountApprovedSampleXml($id); - break; - case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED: - $subjectXml = self::_merchantAccountDeclinedSampleXml($id); - break; - case Braintree_WebhookNotification::TRANSACTION_DISBURSED: - $subjectXml = self::_transactionDisbursedSampleXml($id); - break; - case Braintree_WebhookNotification::DISBURSEMENT_EXCEPTION: - $subjectXml = self::_disbursementExceptionSampleXml($id); - break; - case Braintree_WebhookNotification::DISBURSEMENT: - $subjectXml = self::_disbursementSampleXml($id); - break; - case Braintree_WebhookNotification::PARTNER_MERCHANT_CONNECTED: - $subjectXml = self::_partnerMerchantConnectedSampleXml($id); - break; - case Braintree_WebhookNotification::PARTNER_MERCHANT_DISCONNECTED: - $subjectXml = self::_partnerMerchantDisconnectedSampleXml($id); - break; - case Braintree_WebhookNotification::PARTNER_MERCHANT_DECLINED: - $subjectXml = self::_partnerMerchantDeclinedSampleXml($id); - break; - default: - $subjectXml = self::_subscriptionSampleXml($id); - break; - } - $timestamp = self::_timestamp(); - return " - - {$timestamp} - {$kind} - {$subjectXml} - - "; - } - - private static function _merchantAccountApprovedSampleXml($id) - { - return " - - {$id} - - master_ma_for_{$id} - active - - active - - "; - } - - private static function _merchantAccountDeclinedSampleXml($id) - { - return " - - Credit score is too low - - - - - - 82621 - Credit score is too low - base - - - - - - {$id} - suspended - - master_ma_for_{$id} - suspended - - - - "; - } - - private static function _transactionDisbursedSampleXml($id) - { - return " - - ${id} - 100 - - 2013-07-09 - - - "; - } - - private static function _disbursementExceptionSampleXml($id) - { - return " - - ${id} - - asdfg - qwert - - false - false - - merchant_account_token - USD - false - active - - 100.00 - 2014-02-10 - bank_rejected - update_funding_information - - "; - } - - private static function _disbursementSampleXml($id) - { - return " - - ${id} - - asdfg - qwert - - true - false - - merchant_account_token - USD - false - active - - 100.00 - 2014-02-10 - - - - "; - } - - private static function _subscriptionSampleXml($id) - { - return " - - {$id} - - - - - - - - "; - } - - private static function _partnerMerchantConnectedSampleXml($id) - { - return " - - public_id - public_key - private_key - abc123 - cse_key - - "; - } +namespace Braintree; - private static function _partnerMerchantDisconnectedSampleXml($id) - { - return " - - abc123 - - "; - } - - private static function _partnerMerchantDeclinedSampleXml($id) - { - return " - - abc123 - - "; - } - - private static function _timestamp() +class WebhookTesting +{ + public static function sampleNotification($kind, $id, $sourceMerchantId = null) { - $originalZone = date_default_timezone_get(); - date_default_timezone_set('UTC'); - $timestamp = strftime('%Y-%m-%dT%TZ'); - date_default_timezone_set($originalZone); - - return $timestamp; + return Configuration::gateway()->webhookTesting()->sampleNotification($kind, $id, $sourceMerchantId); } } +class_alias('Braintree\WebhookTesting', 'Braintree_WebhookTesting'); diff --git a/lib/Braintree/WebhookTestingGateway.php b/lib/Braintree/WebhookTestingGateway.php new file mode 100644 index 0000000..ce675c9 --- /dev/null +++ b/lib/Braintree/WebhookTestingGateway.php @@ -0,0 +1,553 @@ +config = $gateway->config; + $this->config->assertHasAccessTokenOrKeys(); + } + + public function sampleNotification($kind, $id, $sourceMerchantId = null) + { + $xml = self::_sampleXml($kind, $id, $sourceMerchantId); + $payload = base64_encode($xml) . "\n"; + $signature = $this->config->getPublicKey() . "|" . Digest::hexDigestSha1($this->config->getPrivateKey(), $payload); + + return [ + 'bt_signature' => $signature, + 'bt_payload' => $payload + ]; + } + + private static function _sampleXml($kind, $id, $sourceMerchantId) + { + switch ($kind) { + case WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED: + $subjectXml = self::_merchantAccountApprovedSampleXml($id); + break; + case WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED: + $subjectXml = self::_merchantAccountDeclinedSampleXml($id); + break; + case WebhookNotification::TRANSACTION_DISBURSED: + $subjectXml = self::_transactionDisbursedSampleXml($id); + break; + case WebhookNotification::TRANSACTION_SETTLED: + $subjectXml = self::_transactionSettledSampleXml($id); + break; + case WebhookNotification::TRANSACTION_SETTLEMENT_DECLINED: + $subjectXml = self::_transactionSettlementDeclinedSampleXml($id); + break; + case WebhookNotification::DISBURSEMENT_EXCEPTION: + $subjectXml = self::_disbursementExceptionSampleXml($id); + break; + case WebhookNotification::DISBURSEMENT: + $subjectXml = self::_disbursementSampleXml($id); + break; + case WebhookNotification::PARTNER_MERCHANT_CONNECTED: + $subjectXml = self::_partnerMerchantConnectedSampleXml($id); + break; + case WebhookNotification::PARTNER_MERCHANT_DISCONNECTED: + $subjectXml = self::_partnerMerchantDisconnectedSampleXml($id); + break; + case WebhookNotification::PARTNER_MERCHANT_DECLINED: + $subjectXml = self::_partnerMerchantDeclinedSampleXml($id); + break; + case WebhookNotification::OAUTH_ACCESS_REVOKED: + $subjectXml = self::_oauthAccessRevocationSampleXml($id); + break; + case WebhookNotification::CONNECTED_MERCHANT_STATUS_TRANSITIONED: + $subjectXml = self::_connectedMerchantStatusTransitionedSampleXml($id); + break; + case WebhookNotification::CONNECTED_MERCHANT_PAYPAL_STATUS_CHANGED: + $subjectXml = self::_connectedMerchantPayPalStatusChangedSampleXml($id); + break; + case WebhookNotification::DISPUTE_OPENED: + $subjectXml = self::_disputeOpenedSampleXml($id); + break; + case WebhookNotification::DISPUTE_LOST: + $subjectXml = self::_disputeLostSampleXml($id); + break; + case WebhookNotification::DISPUTE_WON: + $subjectXml = self::_disputeWonSampleXml($id); + break; + case WebhookNotification::SUBSCRIPTION_CHARGED_SUCCESSFULLY: + $subjectXml = self::_subscriptionChargedSuccessfullySampleXml($id); + break; + case WebhookNotification::SUBSCRIPTION_CHARGED_UNSUCCESSFULLY: + $subjectXml = self::_subscriptionChargedUnsuccessfullySampleXml($id); + break; + case WebhookNotification::CHECK: + $subjectXml = self::_checkSampleXml(); + break; + case WebhookNotification::ACCOUNT_UPDATER_DAILY_REPORT: + $subjectXml = self::_accountUpdaterDailyReportSampleXml($id); + break; + case WebhookNotification::IDEAL_PAYMENT_COMPLETE: + $subjectXml = self::_idealPaymentCompleteSampleXml($id); + break; + case WebhookNotification::IDEAL_PAYMENT_FAILED: + $subjectXml = self::_idealPaymentFailedSampleXml($id); + break; + case WebhookNotification::GRANTED_PAYMENT_INSTRUMENT_UPDATE: + $subjectXml = self::_grantedPaymentInstrumentUpdateSampleXml(); + break; + case WebhookNotification::LOCAL_PAYMENT_COMPLETED: + $subjectXml = self::_localPaymentCompletedSampleXml(); + break; + default: + $subjectXml = self::_subscriptionSampleXml($id); + break; + } + $timestamp = self::_timestamp(); + + $sourceMerchantIdXml = ''; + if (!is_null($sourceMerchantId)) { + $sourceMerchantIdXml = "{$sourceMerchantId}"; + } + + return " + + {$timestamp} + {$kind} + {$sourceMerchantIdXml} + {$subjectXml} + + "; + } + + private static function _merchantAccountApprovedSampleXml($id) + { + return " + + {$id} + + master_ma_for_{$id} + active + + active + + "; + } + + private static function _merchantAccountDeclinedSampleXml($id) + { + return " + + Credit score is too low + + + + + + 82621 + Credit score is too low + base + + + + + + {$id} + suspended + + master_ma_for_{$id} + suspended + + + + "; + } + + private static function _transactionDisbursedSampleXml($id) + { + return " + + ${id} + 100 + + 2013-07-09 + + + "; + } + + private static function _transactionSettledSampleXml($id) + { + return " + + ${id} + settled + sale + USD + 100.00 + ogaotkivejpfayqfeaimuktty + us_bank_account + + 123456789 + 1234 + checking + Dan Schulman + + + "; + } + + private static function _transactionSettlementDeclinedSampleXml($id) + { + return " + + ${id} + settlement_declined + sale + USD + 100.00 + ogaotkivejpfayqfeaimuktty + us_bank_account + + 123456789 + 1234 + checking + Dan Schulman + + + "; + } + + private static function _disbursementExceptionSampleXml($id) + { + return " + + ${id} + + asdfg + qwert + + false + false + + merchant_account_token + USD + false + active + + 100.00 + 2014-02-10 + bank_rejected + update_funding_information + + "; + } + + private static function _disbursementSampleXml($id) + { + return " + + ${id} + + asdfg + qwert + + true + false + + merchant_account_token + USD + false + active + + 100.00 + 2014-02-10 + + + + "; + } + + private static function _disputeOpenedSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + open + fraud + ${id} + + ${id} + 250.00 + + 2014-03-21 + + "; + } + + private static function _disputeLostSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + lost + fraud + ${id} + + ${id} + 250.00 + 2020-02-10 + + 2014-03-21 + + "; + } + + private static function _disputeWonSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + won + fraud + ${id} + + ${id} + 250.00 + + 2014-03-21 + 2014-03-22 + + "; + } + + private static function _subscriptionSampleXml($id) + { + return " + + {$id} + + + + + + + + "; + } + + private static function _subscriptionChargedSuccessfullySampleXml($id) + { + return " + + {$id} + 2016-03-21 + 2017-03-31 + + + {$id} + submitted_for_settlement + 49.99 + + + + + + + + "; + } + + private static function _subscriptionChargedUnsuccessfullySampleXml($id) + { + return " + + {$id} + 2016-03-21 + 2017-03-31 + + + {$id} + failed + 49.99 + + + + + + + + "; + } + + private static function _checkSampleXml() + { + return " + true + "; + } + + private static function _partnerMerchantConnectedSampleXml($id) + { + return " + + public_id + public_key + private_key + abc123 + cse_key + + "; + } + + private static function _partnerMerchantDisconnectedSampleXml($id) + { + return " + + abc123 + + "; + } + + private static function _partnerMerchantDeclinedSampleXml($id) + { + return " + + abc123 + + "; + } + + private static function _oauthAccessRevocationSampleXml($id) + { + return " + + {$id} + oauth_application_client_id + + "; + } + + private static function _accountUpdaterDailyReportSampleXml($id) + { + return " + + 2016-01-14 + link-to-csv-report + + "; + } + + private static function _connectedMerchantStatusTransitionedSampleXml($id) + { + return " + + {$id} + new_status + oauth_application_client_id + + "; + } + + private static function _connectedMerchantPayPalStatusChangedSampleXml($id) + { + return " + + {$id} + link + oauth_application_client_id + + "; + } + + private static function _idealPaymentCompleteSampleXml($id) + { + return " + + {$id} + COMPLETE + ABCISSUER + ORDERABC + EUR + 10.00 + 2016-11-29T23:27:34.547Z + https://example.com + 1234567890 + + "; + } + + private static function _idealPaymentFailedSampleXml($id) + { + return " + + {$id} + FAILED + ABCISSUER + ORDERABC + EUR + 10.00 + 2016-11-29T23:27:34.547Z + https://example.com + 1234567890 + + "; + } + + private static function _grantedPaymentInstrumentUpdateSampleXml() + { + return " + + vczo7jqrpwrsi2px + cf0i8wgarszuy6hc + + ee257d98-de40-47e8-96b3-a6954ea7a9a4 + false + false + + abc123z + + expiration-month + expiration-year + + + "; + } + + private static function _localPaymentCompletedSampleXml() + { + return " + + a-payment-id + a-payer-id + + "; + } + + private static function _timestamp() + { + $originalZone = date_default_timezone_get(); + date_default_timezone_set('UTC'); + $timestamp = strftime('%Y-%m-%dT%TZ'); + date_default_timezone_set($originalZone); + + return $timestamp; + } +} +class_alias('Braintree\WebhookTestingGateway', 'Braintree_WebhookTestingGateway'); diff --git a/lib/Braintree/Xml.php b/lib/Braintree/Xml.php index a6e5119..e938c40 100644 --- a/lib/Braintree/Xml.php +++ b/lib/Braintree/Xml.php @@ -1,17 +1,12 @@ openMemory(); @@ -33,7 +37,7 @@ public static function arrayToXml($aData) $aKeys = array_keys($aData); $rootElementName = $aKeys[0]; // open the root element - $writer->startElement(Braintree_Util::camelCaseToDelimiter($rootElementName)); + $writer->startElement($rootElementName); // create the body self::_createElementsFromArray($writer, $aData[$rootElementName], $rootElementName); @@ -52,7 +56,7 @@ public static function arrayToXml($aData) * @static * @param object $writer XMLWriter object * @param array $aData contains attributes and values - * @return none + * @return void */ private static function _createElementsFromArray(&$writer, $aData) { @@ -64,9 +68,7 @@ private static function _createElementsFromArray(&$writer, $aData) } return; } - foreach ($aData AS $index => $element) { - // convert the style back to gateway format - $elementName = Braintree_Util::camelCaseToDelimiter($index, '-'); + foreach ($aData AS $elementName => $element) { // handle child elements $writer->startElement($elementName); if (is_array($element)) { @@ -104,28 +106,30 @@ private static function _createElementsFromArray(&$writer, $aData) private static function _generateXmlAttribute($value) { if ($value instanceof DateTime) { - return array('type', 'datetime', self::_dateTimeToXmlTimestamp($value)); + return ['type', 'datetime', self::_dateTimeToXmlTimestamp($value)]; } if (is_int($value)) { - return array('type', 'integer', $value); + return ['type', 'integer', $value]; } if (is_bool($value)) { - return array('type', 'boolean', ($value ? 'true' : 'false')); + return ['type', 'boolean', ($value ? 'true' : 'false')]; } if ($value === NULL) { - return array('nil', 'true', $value); + return ['nil', 'true', $value]; } } /** * converts datetime back to xml schema format * @access protected * @param object $dateTime - * @return var XML schema formatted timestamp + * @return string XML schema formatted timestamp */ private static function _dateTimeToXmlTimestamp($dateTime) { - $dateTime->setTimeZone(new DateTimeZone('UTC')); - return ($dateTime->format('Y-m-d\TH:i:s') . 'Z'); + $dateTimeForUTC = clone $dateTime; + + $dateTimeForUTC->setTimeZone(new DateTimeZone('UTC')); + return ($dateTimeForUTC->format('Y-m-d\TH:i:s') . 'Z'); } private static function _castDateTime($string) @@ -142,3 +146,4 @@ private static function _castDateTime($string) } } } +class_alias('Braintree\Xml\Generator', 'Braintree_Xml_Generator'); diff --git a/lib/Braintree/Xml/Parser.php b/lib/Braintree/Xml/Parser.php index e4fea27..1c0d05e 100644 --- a/lib/Braintree/Xml/Parser.php +++ b/lib/Braintree/Xml/Parser.php @@ -1,179 +1,140 @@ getName()); - $type = $iterator->attributes()->type; - - self::$_xmlRoot = $iterator->getName(); - self::$_responseType = $type; + $document = new DOMDocument('1.0', 'UTF-8'); + $document->loadXML($xml); - // return the mapped array with the root element as the header - return array($xmlRoot => self::_iteratorToArray($iterator)); + $root = $document->documentElement->nodeName; + return Util::delimiterToCamelCaseArray([ + $root => self::_nodeToValue($document->childNodes->item(0)), + ]); } /** - * processes SimpleXMLIterator objects recursively + * Converts a node to an array of values or nodes * - * @access protected - * @param object $iterator - * @return array xml converted to array + * @param DOMNode @node + * @return mixed */ - private static function _iteratorToArray($iterator) + private static function _nodeToArray($node) { - $xmlArray = array(); - $value = null; - - // rewind the iterator and check if the position is valid - // if not, return the string it contains - $iterator->rewind(); - if (!$iterator->valid()) { - return self::_typecastXmlValue($iterator); + $type = null; + if ($node instanceof DOMElement) { + $type = $node->getAttribute('type'); } - for ($iterator->rewind(); $iterator->valid(); $iterator->next()) { - - $tmpArray = null; - $value = null; - - // get the attribute type string for use in conditions below - $attributeType = $iterator->attributes()->type; - - // extract the parent element via xpath query - $parentElement = $iterator->xpath($iterator->key() . '/..'); - if ($parentElement[0] instanceof SimpleXMLIterator) { - $parentElement = $parentElement[0]; - $parentKey = Braintree_Util::delimiterToCamelCase($parentElement->getName()); - } else { - $parentElement = null; - } - - - if ($parentKey == "customFields") { - $key = Braintree_Util::delimiterToUnderscore($iterator->key()); - } else { - $key = Braintree_Util::delimiterToCamelCase($iterator->key()); - } - - // process children recursively - if ($iterator->hasChildren()) { - // return the child elements - $value = self::_iteratorToArray($iterator->current()); - // if the element is an array type, - // use numeric keys to allow multiple values - if ($attributeType != 'array') { - $tmpArray[$key] = $value; + switch($type) { + case 'array': + $array = []; + foreach ($node->childNodes as $child) { + $value = self::_nodeToValue($child); + if ($value !== null) { + $array[] = $value; } - } else { - // cast values according to attributes - $tmpArray[$key] = self::_typecastXmlValue($iterator->current()); } - - // set the output string - $output = isset($value) ? $value : $tmpArray[$key]; - - // determine if there are multiple tags of this name at the same level - if (isset($parentElement) && - ($parentElement->attributes()->type == 'collection') && - $iterator->hasChildren()) { - $xmlArray[$key][] = $output; - continue; + return $array; + case 'collection': + $collection = []; + foreach ($node->childNodes as $child) { + $value = self::_nodetoValue($child); + if ($value !== null) { + if (!isset($collection[$child->nodeName])) { + $collection[$child->nodeName] = []; + } + $collection[$child->nodeName][] = self::_nodeToValue($child); + } } - - // if the element was an array type, output to a numbered key - // otherwise, use the element name - if ($attributeType == 'array') { - $xmlArray[] = $output; + return $collection; + default: + $values = []; + if ($node->childNodes->length === 1 && $node->childNodes->item(0) instanceof DOMText) { + return $node->childNodes->item(0)->nodeValue; } else { - $xmlArray[$key] = $output; + foreach ($node->childNodes as $child) { + if (!$child instanceof DOMText) { + $values[$child->nodeName] = self::_nodeToValue($child); + } + } + return $values; } } - - return $xmlArray; } /** - * typecast xml value based on attributes - * @param object $valueObj SimpleXMLElement - * @return mixed value for placing into array + * Converts a node to a PHP value + * + * @param DOMNode $node + * @return mixed */ - private static function _typecastXmlValue($valueObj) + private static function _nodeToValue($node) { - // get the element attributes - $attribs = $valueObj->attributes(); - // the element is null, so jump out here - if (isset($attribs->nil) && $attribs->nil) { - return null; - } - // switch on the type attribute - // switch works even if $attribs->type isn't set - switch ($attribs->type) { - case 'datetime': - return self::_timestampToUTC((string) $valueObj); - break; - case 'date': - return new DateTime((string)$valueObj); - break; - case 'integer': - return (int) $valueObj; - break; - case 'boolean': - $value = (string) $valueObj; - // look for a number inside the string - if(is_numeric($value)) { - return (bool) $value; - } else { - // look for the string "true", return false in all other cases - return ($value != "true") ? FALSE : TRUE; - } - break; - case 'array': - return array(); - default: - return (string) $valueObj; + $type = null; + if ($node instanceof DOMElement) { + $type = $node->getAttribute('type'); } + switch($type) { + case 'datetime': + return self::_timestampToUTC((string) $node->nodeValue); + case 'date': + return new DateTime((string) $node->nodeValue); + case 'integer': + return (int) $node->nodeValue; + case 'boolean': + $value = (string) $node->nodeValue; + if(is_numeric($value)) { + return (bool) $value; + } else { + return ($value !== "true") ? false : true; + } + case 'array': + case 'collection': + return self::_nodeToArray($node); + default: + if ($node->hasChildNodes()) { + return self::_nodeToArray($node); + } elseif (trim($node->nodeValue) === '') { + return null; + } else { + return $node->nodeValue; + } + } } + /** - * convert xml timestamps into DateTime + * Converts XML timestamps into DateTime instances + * * @param string $timestamp - * @return string UTC formatted datetime string + * @return DateTime */ private static function _timestampToUTC($timestamp) { $tz = new DateTimeZone('UTC'); - // strangely DateTime requires an explicit set below - // to show the proper time zone $dateTime = new DateTime($timestamp, $tz); $dateTime->setTimezone($tz); return $dateTime; } } +class_alias('Braintree\Xml\Parser', 'Braintree_Xml_Parser'); diff --git a/lib/autoload.php b/lib/autoload.php new file mode 100644 index 0000000..1b5edc0 --- /dev/null +++ b/lib/autoload.php @@ -0,0 +1,21 @@ + Date: Sat, 17 Nov 2018 16:37:16 +0530 Subject: [PATCH 05/99] Added bn code value in the sale transaction request, ref #2 --- lib/class.plugify-gform-braintree.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 944b334..c1ec92c 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -86,6 +86,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { // Prepare Braintree payload $args = array( 'amount' => $submission_data['payment_amount'], + 'channel' => 'AngellEYEPayPalforWoo_BT', 'creditCard' => array( 'number' => $card_number, 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), From c56559127839cc4946e5d17a530e5db8f04065cf Mon Sep 17 00:00:00 2001 From: angelleye Date: Sat, 17 Nov 2018 05:33:17 -0600 Subject: [PATCH 06/99] Updates details for AE release, ref Issue-3 --- gravity-forms-braintree.php | 24 +++++++------ readme.txt | 67 ++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/gravity-forms-braintree.php b/gravity-forms-braintree.php index 5426412..fe20543 100644 --- a/gravity-forms-braintree.php +++ b/gravity-forms-braintree.php @@ -1,12 +1,18 @@ diff --git a/readme.txt b/readme.txt index a3a02c8..321e0eb 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ -=== Gravity Forms Braintree Add-On === -Contributors: Plugify, hello@lukerollans.me, gravityplus -Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=hello%40plugify%2eio&lc=GB&item_name=Plugin%20Development%20Donation¤cy_code=USD -Tags: credit card,braintree,gravity form,payment +=== Gravity Forms Braintree Payments === +Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus +Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url +Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 3.9 -Stable tag: 1.1.2 +Tested up to: 4.9.8 +Stable tag: 2.0.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -12,54 +12,60 @@ Allow your customers to purchase goods and services through Gravity Forms via Br == Description == -Braintree Payments is a payment gateway provider owned by eBAY Inc, which allows you to proces credit card payments without the need for a bank merchant account and full PCI-compliance. No sensitive data such as credit card numbers are stored on your server, Braintree takes care of everything. +Braintree Payments is a payment gateway provider owned by PayPal which allows you to process credit card payments without the need for a bank merchant account and full PCI-compliance. No sensitive data such as credit card numbers are stored on your server, Braintree takes care of everything. > Requires at least WordPress 3.8 and Gravity Forms 1.8 There are just a few simple steps to begin leveraging your Braintree Payments account: -1. Install Gravity Forms Braintree Add-On -2. Go to the Form Settings page for the form you wish to create a Braintree feed on +1. Install Gravity Forms Braintree Payments. +2. Go to the Form Settings page for the form you wish to create a Braintree feed on. 3. You will be prompted to configure your Braintree settings. Click the link provided to do so. 4. Once you have configured your Braintree settings, return to the Form Settings page and follow the prompts. = Features = -* Seamlessly integrates your Gravity Forms credit card forms with Braintree Payments -* Supports both production and sandbox environments, enabling you to test payments before going live -* Form entries will only be created when payment is successful -* Quick and easy setup - -If you have found this plugin useful, consider taking a moment to rate it, or perhaps even a small donation. +* Seamlessly integrates your Gravity Forms credit card forms with Braintree Payments. +* Supports both production and sandbox environments, enabling you to test payments before going live. +* Form entries will only be created when payment is successful. +* Quick and easy setup. == Installation == -1. Upload the `gravity-forms-braintree` folder to the `/wp-content/plugins/` directory. -2. Activate the plugin through the 'Plugins' menu in WordPress. -3. Navigate to the Form you wish to setup with a Braintree feed. -4. Under Form Settings, choose the Braintree option. += Automatic installation = + +Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't need to leave your web browser. To do an automatic install of Gravity Forms Braintree Payments, log in to your WordPress dashboard, navigate to the Plugins menu and click Add New. + +In the search field type Gravity Forms Braintree Payments and click Search Plugins. Once you've found our plugin (make sure it says "by Angell EYE") you can view details about it such as the the rating and description. Most importantly, of course, you can install it by simply clicking Install Now. + += Manual Installation = + +1. Unzip the files and upload the folder into your plugins folder (/wp-content/plugins/) overwriting older versions if they exist +2. Activate the plugin in your WordPress admin area. + += Usage = + +1. Navigate to the Form you wish to setup with a Braintree feed. +2. Under Form Settings, choose the Braintree option. == Frequently asked questions == = What type of Braintree payments can be accepted? = -For this early version, only one off payments can be accepted. Subscriptions will be available in version 1.1 - -= Can I use conditional logic? EG, I only want to register a user if the Braintree payment was successful = -In version 1.0, no. This is planned for version 1.2, coming very soon +* For this early version, only one off payments can be accepted. = Does this plugin support Braintree subscriptions? = -Not currently, no. This will be released very shortly in version 1.1 - -= Available filters and actions = -No filters are currently available for this pre-release version +* Not yet. This will be added based on future demand. == Screenshots == 1. Easily configure your Braintree settings, allowing for quick and efficient setup. -2. Quickly and easily configure payment feeds under Form Settings of any Gravity Form -3. List of active feeds on the current form +2. Quickly and easily configure payment feeds under Form Settings of any Gravity Form. +3. List of active feeds on the current form. == Changelog == += 2.0.0 = +* Fix - Updates Braintree Payments SDK and resolves failures with latest version of Gravity Forms. ([#1](https://github.com/angelleye/gravity-forms-braintree/issues/1)) + = 1.1.2 = * Internal maintenance release. Version 1.2 is coming soon and it's going to be big! @@ -86,4 +92,5 @@ No filters are currently available for this pre-release version == Upgrade notice == -IMPORTANT! Version 1.0 is a complete overhaul from the previous version. Your existing feeds will not work. Please make sure you check all your feeds and ensure they function correctly. += 2.0.0 = +This is a forked version of the original Gravity Forms Braintree Add-On by Plugify. It has been updated to work with the latest version of Braintree and Gravity Forms, and will be maintained. \ No newline at end of file From ae1ab0a43c6ea842ded8e5114500bd1f2c89a5a7 Mon Sep 17 00:00:00 2001 From: angelleye Date: Sat, 17 Nov 2018 05:40:31 -0600 Subject: [PATCH 07/99] Updates details, ref Issue-3 --- README.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 991f90f..42ea532 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,28 @@ # Integrate Gravity Forms with Braintree -Braintree Payments is a payment gateway provider owned by eBAY Inc, which allows you to proces credit card payments without the need for a bank merchant account and full PCI-compliance. No sensitive data such as credit card numbers are stored on your server, Braintree takes care of everything. - -#### If you have found this plugin useful, consider taking a moment to rate it, or perhaps even a small donation. +Braintree Payments is a payment gateway provider owned by PayPal which allows you to process credit card payments without the need for a bank merchant account and full PCI-compliance. No sensitive data such as credit card numbers are stored on your server, Braintree takes care of everything. ## Installation -1. Upload the `gravity-forms-braintree` folder to the `/wp-content/plugins/` directory. -2. Activate the plugin through the 'Plugins' menu in WordPress. -3. Navigate to the Form you wish to setup with a Braintree feed. -4. Under Form Settings, choose the Braintree option. +### Automatic installation -## Features +Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't need to leave your web browser. To do an automatic install of Gravity Forms Braintree Payments, log in to your WordPress dashboard, navigate to the Plugins menu and click Add New. + +In the search field type Gravity Forms Braintree Payments and click Search Plugins. Once you've found our plugin (make sure it says "by Angell EYE") you can view details about it such as the the rating and description. Most importantly, of course, you can install it by simply clicking Install Now. + +### Manual Installation -* Seamlessly integrates your Gravity Forms credit card forms with Braintree Payments -* Supports both production and sandbox environments, enabling you to test payments before going live -* Form entries will only be created when payment is successful -* Quick and easy setup +1. Unzip the files and upload the folder into your plugins folder (/wp-content/plugins/) overwriting older versions if they exist +2. Activate the plugin in your WordPress admin area. -## Subscriptions -The plugin does not currently support Braintree Subscriptions. Keep a look out for it in a future version +### Usage + +1. Navigate to the Form you wish to setup with a Braintree feed. +2. Under Form Settings, choose the Braintree option. + +## Features -## Upgrade Notice -If you are updating from a version previous to 1.0, your existing feeds will not work. Please make sure you check all your feeds and ensure they function correctly. +* Seamlessly integrates your Gravity Forms credit card forms with Braintree Payments. +* Supports both production and sandbox environments, enabling you to test payments before going live. +* Form entries will only be created when payment is successful. +* Quick and easy setup. \ No newline at end of file From 341bcbec6728a989acc1320dafd7e263912a2917 Mon Sep 17 00:00:00 2001 From: angelleye Date: Sat, 17 Nov 2018 05:42:55 -0600 Subject: [PATCH 08/99] Renames file, ref #3 --- ...y-forms-braintree.php => angelleye-gravity-forms-braintree.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename gravity-forms-braintree.php => angelleye-gravity-forms-braintree.php (100%) diff --git a/gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php similarity index 100% rename from gravity-forms-braintree.php rename to angelleye-gravity-forms-braintree.php From f40add6c9144db9029d6a570ed77630f975a1c00 Mon Sep 17 00:00:00 2001 From: angelleye Date: Thu, 24 Jan 2019 03:02:44 -0600 Subject: [PATCH 09/99] Updates tested version --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 321e0eb..94fff64 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 4.9.8 +Tested up to: 5.0.3 Stable tag: 2.0.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From b5c485b6556a02701090dbab0c025108f37abe99 Mon Sep 17 00:00:00 2001 From: angelleye Date: Wed, 27 Feb 2019 08:21:20 -0600 Subject: [PATCH 10/99] Updates tested version, GFB-3 --- readme.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index 94fff64..1c5f309 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.0.3 +Tested up to: 5.1 Stable tag: 2.0.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -57,9 +57,10 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi * Not yet. This will be added based on future demand. == Screenshots == -1. Easily configure your Braintree settings, allowing for quick and efficient setup. -2. Quickly and easily configure payment feeds under Form Settings of any Gravity Form. -3. List of active feeds on the current form. +1. Drop a credit card field collection directly into any Gravity Form. +2. Easily configure your Braintree settings, allowing for quick and efficient setup. +3. Quickly and easily configure payment feeds under Form Settings of any Gravity Form. +4. List of active feeds on the current form. == Changelog == From 345dc31c75bf6ff39f753ab28af1aab83d951ed4 Mon Sep 17 00:00:00 2001 From: tejas Date: Tue, 26 Mar 2019 11:40:11 +0530 Subject: [PATCH 11/99] GFB-4 , Updater compatibility --- angelleye-gravity-forms-braintree.php | 12 ++++ includes/angelleye-functions.php | 85 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 includes/angelleye-functions.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index fe20543..6032326 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -19,6 +19,11 @@ exit; } +if (!defined('AEU_ZIP_URL')) { + define('AEU_ZIP_URL', 'https://github.com/angelleye/angelleye-updater/archive/master.zip'); +} + + $path = trailingslashit( dirname( __FILE__ ) ); // Ensure Gravity Forms (payment addon framework) is installed and good to go @@ -33,6 +38,13 @@ // Require plugin entry point require_once $path . 'lib/class.plugify-gform-braintree.php'; + /** + * Required functions + */ + if (!function_exists('angelleye_queue_update')) { + require_once( 'includes/angelleye-functions.php' ); + } + // Fire off entry point new Plugify_GForm_Braintree(); diff --git a/includes/angelleye-functions.php b/includes/angelleye-functions.php new file mode 100644 index 0000000..aa876bc --- /dev/null +++ b/includes/angelleye-functions.php @@ -0,0 +1,85 @@ +file = $file; + $plugin->file_id = $file_id; + $plugin->product_id = $product_id; + + $angelleye_queued_updates[] = $plugin; + } + +} + + +/** + * Load installer for the AngellEYE Updater. + * @return $api Object + */ +if (!class_exists('AngellEYE_Updater') && !function_exists('angell_updater_install')) { + + function angell_updater_install($api, $action, $args) { + $download_url = AEU_ZIP_URL; + + if ('plugin_information' != $action || + false !== $api || + !isset($args->slug) || + 'angelleye-updater' != $args->slug + ) + return $api; + + $api = new stdClass(); + $api->name = 'AngellEYE Updater'; + $api->version = ''; + $api->download_link = esc_url($download_url); + return $api; + } + + add_filter('plugins_api', 'angell_updater_install', 10, 3); +} + +/** + * AngellEYE Installation Prompts + */ +if (!class_exists('AngellEYE_Updater') && !function_exists('angell_updater_notice')) { + + /** + * Display a notice if the "AngellEYE Updater" plugin hasn't been installed. + * @return void + */ + function angell_updater_notice() { + $active_plugins = apply_filters('active_plugins', get_option('active_plugins')); + if (in_array('angelleye-updater/angelleye-updater.php', $active_plugins)) + return; + + $slug = 'angelleye-updater'; + $install_url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $slug), 'install-plugin_' . $slug); + $activate_url = 'plugins.php?action=activate&plugin=' . urlencode('angelleye-updater/angelleye-updater.php') . '&plugin_status=all&paged=1&s&_wpnonce=' . urlencode(wp_create_nonce('activate-plugin_angelleye-updater/angelleye-updater.php')); + + $message = 'Install the Angell EYE Updater plugin to get updates for your Angell EYE plugins.'; + $is_downloaded = false; + $plugins = array_keys(get_plugins()); + foreach ($plugins as $plugin) { + if (strpos($plugin, 'angelleye-updater.php') !== false) { + $is_downloaded = true; + $message = ' Activate the Angell EYE Updater plugin to get updates for your Angell EYE plugins.'; + } + } + echo '

' . $message . '

' . "\n"; + } + + add_action('admin_notices', 'angell_updater_notice'); +} \ No newline at end of file From 640d9d26d06bddcf28ff53272fb962fa10ae16ea Mon Sep 17 00:00:00 2001 From: angelleye Date: Wed, 27 Mar 2019 18:25:28 -0500 Subject: [PATCH 12/99] Updates changelog, GFB-4 --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index 1c5f309..84a6d6f 100644 --- a/readme.txt +++ b/readme.txt @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.0.1 = +* Feature - Adds AE Updater compatibility for future notices and automated updates. [GFB-4] + = 2.0.0 = * Fix - Updates Braintree Payments SDK and resolves failures with latest version of Gravity Forms. ([#1](https://github.com/angelleye/gravity-forms-braintree/issues/1)) From 670a82301f9c619a59778b7f05f1020445abe023 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 4 Apr 2019 11:09:17 +0530 Subject: [PATCH 13/99] AE Updater plugin link, GFB-5 --- angelleye-gravity-forms-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 6032326..761e563 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -20,7 +20,7 @@ } if (!defined('AEU_ZIP_URL')) { - define('AEU_ZIP_URL', 'https://github.com/angelleye/angelleye-updater/archive/master.zip'); + define('AEU_ZIP_URL', 'https://updates.angelleye.com/ae-updater/angelleye-updater/angelleye-updater.zip'); } From 25cd0700257f1d8d37bb0f5a352d74aa24e54583 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 4 Apr 2019 11:16:44 +0530 Subject: [PATCH 14/99] AE Updater plugin link, GFB-5 --- angelleye-gravity-forms-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 6032326..761e563 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -20,7 +20,7 @@ } if (!defined('AEU_ZIP_URL')) { - define('AEU_ZIP_URL', 'https://github.com/angelleye/angelleye-updater/archive/master.zip'); + define('AEU_ZIP_URL', 'https://updates.angelleye.com/ae-updater/angelleye-updater/angelleye-updater.zip'); } From 68bb4315488953671694e5d2967709fbae87a140 Mon Sep 17 00:00:00 2001 From: angelleye Date: Thu, 4 Apr 2019 03:11:11 -0500 Subject: [PATCH 15/99] Updates changelog, GFB-5 --- readme.txt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/readme.txt b/readme.txt index 84a6d6f..97f2774 100644 --- a/readme.txt +++ b/readme.txt @@ -65,7 +65,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == = 2.0.1 = -* Feature - Adds AE Updater compatibility for future notices and automated updates. [GFB-4] +* Feature - Adds AE Updater compatibility for future notices and automated updates. [GFB-4] ([GFB-5](https://github.com/angelleye/gravity-forms-braintree/pull/8)) = 2.0.0 = * Fix - Updates Braintree Payments SDK and resolves failures with latest version of Gravity Forms. ([#1](https://github.com/angelleye/gravity-forms-braintree/issues/1)) @@ -92,9 +92,4 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi * Most of plugin functionality = 0.1 = -* Initial version of the plugin - -== Upgrade notice == - -= 2.0.0 = -This is a forked version of the original Gravity Forms Braintree Add-On by Plugify. It has been updated to work with the latest version of Braintree and Gravity Forms, and will be maintained. \ No newline at end of file +* Initial version of the plugin \ No newline at end of file From 07b6cd1b5d0cc92e6ea0fbd2d0fbf4f6484d83ee Mon Sep 17 00:00:00 2001 From: angelleye Date: Thu, 4 Apr 2019 03:14:50 -0500 Subject: [PATCH 16/99] Updates details for v2.1.0 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 761e563..14ca907 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.0.0 + * Version: 2.1.0 * Author URI: https://angelleye.com ************* diff --git a/readme.txt b/readme.txt index 97f2774..e0e367f 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.1 -Stable tag: 2.0.0 +Tested up to: 5.1.1 +Stable tag: 2.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.0.1 = += 2.1.0 = * Feature - Adds AE Updater compatibility for future notices and automated updates. [GFB-4] ([GFB-5](https://github.com/angelleye/gravity-forms-braintree/pull/8)) = 2.0.0 = From 4a4d09fcfa0147e4dfe617751d86bb653178a38f Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 5 Apr 2019 18:58:02 +0530 Subject: [PATCH 17/99] add text domain in main file, GFB-7 --- angelleye-gravity-forms-braintree.php | 1 + 1 file changed, 1 insertion(+) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 14ca907..2b99c4d 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -6,6 +6,7 @@ * Author: Angell EYE * Version: 2.1.0 * Author URI: https://angelleye.com + * Text Domain: angelleye-gravity-forms-braintree ************* * Attribution From acfa1024fad969d7d62a271ce41fadf8950d3d83 Mon Sep 17 00:00:00 2001 From: angelleye Date: Thu, 18 Apr 2019 16:17:39 -0500 Subject: [PATCH 18/99] Updates changelog, GFB-7 --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index e0e367f..17f795a 100644 --- a/readme.txt +++ b/readme.txt @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.1.1 - xx.xx.2019 = +* Tweak - Adds text domain. ([GFB-7](https://github.com/angelleye/gravity-forms-braintree/pull/9)) + = 2.1.0 = * Feature - Adds AE Updater compatibility for future notices and automated updates. [GFB-4] ([GFB-5](https://github.com/angelleye/gravity-forms-braintree/pull/8)) From cbbd85e20f684207c9b4528476d99b1376fdad68 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Wed, 8 May 2019 19:17:39 +0530 Subject: [PATCH 19/99] Notification System, GFB-8 --- angelleye-gravity-forms-braintree.php | 8 ++ assets/css/gravity-forms-braintree-admin.css | 74 +++++++++++++++++ assets/css/styles.css | 74 +++++++++++++++++ assets/js/gravity-forms-braintree-admin.js | 19 +++++ assets/js/scripts.js | 2 +- lib/class.plugify-gform-braintree.php | 87 +++++++++++++++++++- 6 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 assets/css/gravity-forms-braintree-admin.css create mode 100644 assets/js/gravity-forms-braintree-admin.js diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 2b99c4d..231a127 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -24,6 +24,14 @@ define('AEU_ZIP_URL', 'https://updates.angelleye.com/ae-updater/angelleye-updater/angelleye-updater.zip'); } +if (!defined('GRAVITY_FORMS_BRAINTREE_ASSET_URL')) { + define('GRAVITY_FORMS_BRAINTREE_ASSET_URL', plugin_dir_url(__FILE__)); +} + +if (!defined('PAYPAL_FOR_WOOCOMMERCE_PUSH_NOTIFICATION_WEB_URL')) { + define('PAYPAL_FOR_WOOCOMMERCE_PUSH_NOTIFICATION_WEB_URL', 'https://www.angelleye.com/'); +} + $path = trailingslashit( dirname( __FILE__ ) ); diff --git a/assets/css/gravity-forms-braintree-admin.css b/assets/css/gravity-forms-braintree-admin.css new file mode 100644 index 0000000..3d1d90e --- /dev/null +++ b/assets/css/gravity-forms-braintree-admin.css @@ -0,0 +1,74 @@ +.notice.notice-success.angelleye-notice { + padding: 0 !important; + margin: 5px 0 10px; + background: #FFF; + overflow: hidden; + -webkit-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05); + position: relative; + z-index: 1; + min-height: 80px; + display: table; /* The magic ingredient! */ + font: 13px "Open Sans", sans-serif; +} +.angelleye-notice > div { + display: table-cell; + vertical-align: middle; + cursor: default; + line-height: 1.5; +} +.angelleye-notice-logo-push { + background-repeat: no-repeat; + background-position: 50% 50%; +} +.angelleye-notice-logo-push span { + display: block; + margin: 0px 10px 0px 10px; +} +.notice.notice-success.angelleye-notice { + font: 13px "Open Sans", sans-serif; + line-height: normal; +} +.angelleye-notice-message { + color: #23282D; + font-size: 13px; + font-weight: normal; + line-height: 20px; + padding: 3px 5px; + -webkit-font-smoothing: antialiased; + width: 100%; +} +.angelleye-notice-message h3 { + margin: 4px 0px !important; +} +.angelleye-notice-message-inner { + margin-bottom: 10px; +} +.angelleye-notice-message p { + margin: 3px 0px !important; + padding: 0px; +} +.angelleye-notice-action { + padding-top: 5px; +} +.angelleye-notice-cta { + border-left: 1px solid #E5E5E5; + background: #F8F8F8; + padding: 0 30px; + position: relative; + white-space: nowrap; +} +.wp-core-ui .angelleye-notice-cta button, +.wp-core-ui .angelleye-notice-cta .button-primary:active { + vertical-align: middle; +} +.angelleye-notice-dismiss { + background: transparent; + border: 0; + cursor: pointer; + color: #C5C5C5; + -webkit-font-smoothing: antialiased; +} + diff --git a/assets/css/styles.css b/assets/css/styles.css index 73216a6..0efd233 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -14,3 +14,77 @@ table.feeds th#id { body { display: none; } + +.notice.notice-success.angelleye-notice { + padding: 0 !important; + margin: 5px 0 10px; + background: #FFF; + overflow: hidden; + -webkit-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05); + position: relative; + z-index: 1; + min-height: 80px; + display: table; /* The magic ingredient! */ + font: 13px "Open Sans", sans-serif; +} +.angelleye-notice > div { + display: table-cell; + vertical-align: middle; + cursor: default; + line-height: 1.5; +} +.angelleye-notice-logo-push { + background-repeat: no-repeat; + background-position: 50% 50%; +} +.angelleye-notice-logo-push span { + display: block; + margin: 0px 10px 0px 10px; +} +.notice.notice-success.angelleye-notice { + font: 13px "Open Sans", sans-serif; + line-height: normal; +} +.angelleye-notice-message { + color: #23282D; + font-size: 13px; + font-weight: normal; + line-height: 20px; + padding: 3px 5px; + -webkit-font-smoothing: antialiased; + width: 100%; +} +.angelleye-notice-message h3 { + margin: 4px 0px !important; +} +.angelleye-notice-message-inner { + margin-bottom: 10px; +} +.angelleye-notice-message p { + margin: 3px 0px !important; + padding: 0px; +} +.angelleye-notice-action { + padding-top: 5px; +} +.angelleye-notice-cta { + border-left: 1px solid #E5E5E5; + background: #F8F8F8; + padding: 0 30px; + position: relative; + white-space: nowrap; +} +.wp-core-ui .angelleye-notice-cta button, +.wp-core-ui .angelleye-notice-cta .button-primary:active { + vertical-align: middle; +} +.angelleye-notice-dismiss { + background: transparent; + border: 0; + cursor: pointer; + color: #C5C5C5; + -webkit-font-smoothing: antialiased; +} \ No newline at end of file diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js new file mode 100644 index 0000000..cddf402 --- /dev/null +++ b/assets/js/gravity-forms-braintree-admin.js @@ -0,0 +1,19 @@ +jQuery(function () { + jQuery('[id^=angelleye_notification]').slice(1).remove(); + var el_notice = jQuery(".angelleye-notice"); + el_notice.fadeIn(750); + jQuery(".angelleye-notice-dismiss").click(function(e){ + e.preventDefault(); + jQuery( this ).parent().parent(".angelleye-notice").fadeOut(600, function () { + jQuery( this ).parent().parent(".angelleye-notice").remove(); + }); + notify_wordpress(jQuery( this ).data("msg")); + }); + function notify_wordpress(message) { + var param = { + action: 'angelleye_gform_braintree_adismiss_notice', + data: message + }; + jQuery.post(ajaxurl, param); + } +}); \ No newline at end of file diff --git a/assets/js/scripts.js b/assets/js/scripts.js index e1fcb85..6145dea 100644 --- a/assets/js/scripts.js +++ b/assets/js/scripts.js @@ -148,4 +148,4 @@ jQuery( function($) { }); -}); +}); \ No newline at end of file diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index c1ec92c..86d5cc5 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -23,8 +23,15 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { */ public function __construct () { + add_action('wp_ajax_angelleye_gform_braintree_adismiss_notice', array($this, 'angelleye_gform_braintree_adismiss_notice'), 10); + add_action('admin_notices', array($this, 'angelleye_gform_braintree_display_push_notification'), 10); + + add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_css'), 10); + add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_js'), 10); // Build parent parent::__construct(); + + } @@ -306,7 +313,79 @@ public function get_plugin_settings () { } } - -} - -?> + + public function angelleye_gform_braintree_display_push_notification() { + global $current_user; + $user_id = $current_user->ID; + $response = $this->angelleye_get_push_notifications(); + if (is_object($response)) { + foreach ($response->data as $key => $response_data) { + if (!get_user_meta($user_id, $response_data->id)) { + $this->angelleye_display_push_notification($response_data); + } + } + } + } + + public function angelleye_get_push_notifications() { + $args = array( + 'plugin_name' => 'angelleye-gravity-forms-braintree', + ); + $api_url = PAYPAL_FOR_WOOCOMMERCE_PUSH_NOTIFICATION_WEB_URL . '?Wordpress_Plugin_Notification_Sender'; + $api_url .= '&action=angelleye_get_plugin_notification'; + $request = wp_remote_post($api_url, array( + 'method' => 'POST', + 'timeout' => 45, + 'redirection' => 5, + 'httpversion' => '1.0', + 'blocking' => true, + 'headers' => array('user-agent' => 'AngellEYE'), + 'body' => $args, + 'cookies' => array(), + 'sslverify' => false + )); + if (is_wp_error($request) or wp_remote_retrieve_response_code($request) != 200) { + return false; + } + if ($request != '') { + $response = json_decode(wp_remote_retrieve_body($request)); + } else { + $response = false; + } + return $response; + } + + public function angelleye_display_push_notification($response_data) { + echo ''; + } + + public function angelleye_gform_braintree_adismiss_notice() { + global $current_user; + $user_id = $current_user->ID; + if (!empty($_POST['action']) && $_POST['action'] == 'angelleye_gform_braintree_adismiss_notice') { + add_user_meta($user_id, wc_clean($_POST['data']), 'true', true); + wp_send_json_success(); + } + } + + public function enqueue_scripts_js() { + wp_enqueue_script('gravity-forms-braintree-admin', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/gravity-forms-braintree-admin.js', array('jquery'), $this->_version, false); + } + + public function enqueue_styles_css() { + wp_enqueue_style('gravity-forms-braintree-admin-css', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/css/gravity-forms-braintree-admin.css', array(), $this->_version, 'all'); + } + +} \ No newline at end of file From c6e772200556b9df496c5ba7e91688e19d0fcf2d Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 10 May 2019 15:27:41 +0530 Subject: [PATCH 20/99] Notification System, GFB-8 --- assets/js/gravity-forms-braintree-admin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index cddf402..b42cd90 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -1,5 +1,7 @@ jQuery(function () { - jQuery('[id^=angelleye_notification]').slice(1).remove(); + jQuery('[id^=angelleye_notification]').each(function (i) { + jQuery('[id="' + this.id + '"]').slice(1).remove(); + }); var el_notice = jQuery(".angelleye-notice"); el_notice.fadeIn(750); jQuery(".angelleye-notice-dismiss").click(function(e){ From 4d5e4bfd33de8ca816777639009064457043d4b1 Mon Sep 17 00:00:00 2001 From: angelleye Date: Fri, 31 May 2019 01:47:29 -0500 Subject: [PATCH 21/99] Updates changelog, GFB-8 --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 17f795a..4340240 100644 --- a/readme.txt +++ b/readme.txt @@ -65,6 +65,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == = 2.1.1 - xx.xx.2019 = +* Feature - Adds AE notification system. ([GFB-8](https://github.com/angelleye/gravity-forms-braintree/pull/10)) * Tweak - Adds text domain. ([GFB-7](https://github.com/angelleye/gravity-forms-braintree/pull/9)) = 2.1.0 = From c9cbdd059489ef93dcd16148185e3ee478411f7d Mon Sep 17 00:00:00 2001 From: angelleye Date: Fri, 31 May 2019 01:58:10 -0500 Subject: [PATCH 22/99] Updates details for v2.1.1 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 231a127..df2b52b 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.1.0 + * Version: 2.1.1 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/readme.txt b/readme.txt index 4340240..88e0087 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.1.1 -Stable tag: 2.1.0 +Tested up to: 5.2.1 +Stable tag: 2.1.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.1.1 - xx.xx.2019 = += 2.1.1 - 05.31.2019 = * Feature - Adds AE notification system. ([GFB-8](https://github.com/angelleye/gravity-forms-braintree/pull/10)) * Tweak - Adds text domain. ([GFB-7](https://github.com/angelleye/gravity-forms-braintree/pull/9)) From 057970aba66e994dd0606e280a29922fad208b32 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 17 Jun 2019 16:53:22 +0530 Subject: [PATCH 23/99] Notification System interval, GFB-9 --- lib/class.plugify-gform-braintree.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 86d5cc5..1f8b6db 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -317,7 +317,12 @@ public function get_plugin_settings () { public function angelleye_gform_braintree_display_push_notification() { global $current_user; $user_id = $current_user->ID; - $response = $this->angelleye_get_push_notifications(); + if (false === ( $response = get_transient('angelleye_push_notification_result') )) { + $response = $this->angelleye_get_push_notifications(); + if(is_object($response)) { + set_transient('angelleye_push_notification_result', $response, 12 * HOUR_IN_SECONDS); + } + } if (is_object($response)) { foreach ($response->data as $key => $response_data) { if (!get_user_meta($user_id, $response_data->id)) { From 611ea186b9190edab1150b8be3b530d095d15dc1 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Tue, 9 Jul 2019 13:17:10 +0530 Subject: [PATCH 24/99] PayPal Adjustments --- lib/class.plugify-gform-braintree.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 86d5cc5..3094ed2 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -93,7 +93,6 @@ public function authorize( $feed, $submission_data, $form, $entry ) { // Prepare Braintree payload $args = array( 'amount' => $submission_data['payment_amount'], - 'channel' => 'AngellEYEPayPalforWoo_BT', 'creditCard' => array( 'number' => $card_number, 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), From 1c77f8a9f2782508c0e5738a73d585ff08c55153 Mon Sep 17 00:00:00 2001 From: angelleye Date: Tue, 9 Jul 2019 02:52:06 -0500 Subject: [PATCH 25/99] Updates details for v2.1.2 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index df2b52b..ba96432 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.1.1 + * Version: 2.1.2 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/readme.txt b/readme.txt index 88e0087..d39d43b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.2.1 -Stable tag: 2.1.1 +Tested up to: 5.2.2 +Stable tag: 2.1.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.1.2 - 07.09.2019 = +* Tweak - Minor adjustments to API request. + = 2.1.1 - 05.31.2019 = * Feature - Adds AE notification system. ([GFB-8](https://github.com/angelleye/gravity-forms-braintree/pull/10)) * Tweak - Adds text domain. ([GFB-7](https://github.com/angelleye/gravity-forms-braintree/pull/9)) From de913eed6ae25729829f25300724d9bbb73c4bc9 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Tue, 9 Jul 2019 17:28:11 +0530 Subject: [PATCH 26/99] Integrate volume tracking system, GFB-11 --- angelleye-gravity-forms-braintree.php | 2 + ...angelleye-gravity-forms-payment-logger.php | 113 ++++++++++++++++++ lib/class.plugify-gform-braintree.php | 6 + 3 files changed, 121 insertions(+) create mode 100644 lib/angelleye-gravity-forms-payment-logger.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index ba96432..eeb98db 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -46,6 +46,7 @@ // Require plugin entry point require_once $path . 'lib/class.plugify-gform-braintree.php'; + require_once $path . 'lib/angelleye-gravity-forms-payment-logger'; /** * Required functions @@ -56,5 +57,6 @@ // Fire off entry point new Plugify_GForm_Braintree(); + AngellEYE_GForm_Braintree_Payment_Logger::instance(); } diff --git a/lib/angelleye-gravity-forms-payment-logger.php b/lib/angelleye-gravity-forms-payment-logger.php new file mode 100644 index 0000000..0da537e --- /dev/null +++ b/lib/angelleye-gravity-forms-payment-logger.php @@ -0,0 +1,113 @@ +api_url = 'https://gtctgyk7fh.execute-api.us-east-2.amazonaws.com/default/PayPalPaymentsTracker'; + $this->api_key = 'srGiuJFpDO4W7YCDXF56g2c9nT1JhlURVGqYD7oa'; + $this->allow_method = array('Braintree'); + add_action('angelleye_gravity_forms_response_data', array($this, 'own_angelleye_gravity_forms_response_data'), 10, 6); + } + + public function own_angelleye_gravity_forms_response_data($result_data, $request_data, $product_id = 1, $sandbox = false, $is_nvp = true, $payment_method = 'express_checkout') { + $request_param = array(); + if (isset($result_data) && is_array($result_data) && !empty($result_data['CURL_ERROR'])) { + return $result_data; + } else { + $result = $result_data; + $request = $request_data; + if ($payment_method == 'braintree') { + $request['METHOD'] = 'Braintree'; + } + if (isset($request['METHOD']) && !empty($request['METHOD']) && in_array($request['METHOD'], $this->allow_method)) { + $opt_in_log = get_option('angelleye_send_opt_in_logging_details', 'no'); + $request_param['site_url'] = ''; + if ($opt_in_log == 'yes') { + $request_param['site_url'] = get_bloginfo('url'); + } + $request_param['type'] = $request['METHOD']; + $request_param['mode'] = ($sandbox) ? 'sandbox' : 'live'; + $request_param['product_id'] = $product_id; + if ($request['METHOD'] == 'Braintree') { + if ($result->success) { + $request_param['status'] = 'Success'; + } else { + $request_param['status'] = 'Failure'; + } + if ($opt_in == 'yes') { + if (isset($result->transaction->statusHistory[0]->user) && !empty($result->transaction->statusHistory[0]->user)) { + $request_param['merchant_id'] = $result->transaction->statusHistory[0]->user; + } + } + $request_param['correlation_id'] = ''; + $request_param['transaction_id'] = isset($result->transaction->id) ? $result->transaction->id : ''; + $request_param['amount'] = isset($result->transaction->amount) ? $result->transaction->amount : '0.00'; + $this->angelleye_tpv_request($request_param); + } + } + } + return $result_data; + } + + public function angelleye_tpv_request($request_param) { + try { + $payment_type = $request_param['type']; + $amount = $request_param['amount']; + $status = $request_param['status']; + $site_url = $request_param['site_url']; + $payment_mode = $request_param['mode']; + $merchant_id = $request_param['merchant_id']; + $correlation_id = $request_param['correlation_id']; + $transaction_id = $request_param['transaction_id']; + $product_id = $request_param['product_id']; + $params = [ + "product_id" => $product_id, + "type" => $payment_type, + "amount" => $amount, + "status" => $status, + "site_url" => $site_url, + "mode" => $payment_mode, + "merchant_id" => $merchant_id, + "correlation_id" => $correlation_id, + "transaction_id" => $transaction_id + ]; + $params = apply_filters('angelleye_log_params', $params); + $post_args = array( + 'headers' => array( + 'Content-Type' => 'application/json; charset=utf-8', + 'x-api-key' => $this->api_key + ), + 'body' => json_encode($params), + 'method' => 'POST', + 'data_format' => 'body', + ); + $response = wp_remote_post($this->api_url, $post_args); + if (is_wp_error($response)) { + $error_message = $response->get_error_message(); + error_log(print_r($error_message, true)); + return false; + } else { + $body = json_decode(wp_remote_retrieve_body($response), true); + if ($body['status']) { + return true; + } + } + return false; + } catch (Exception $ex) { + + } + } + +} diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 3094ed2..ac81d8e 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,6 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { + do_action('angelleye_gravity_forms_response_data', $$result, $submission_data, '1', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; @@ -316,7 +317,12 @@ public function get_plugin_settings () { public function angelleye_gform_braintree_display_push_notification() { global $current_user; $user_id = $current_user->ID; + if (false === ( $response = get_transient('angelleye_push_notification_result') )) { $response = $this->angelleye_get_push_notifications(); + if (is_object($response)) { + set_transient('angelleye_push_notification_result', $response, 12 * HOUR_IN_SECONDS); + } + } if (is_object($response)) { foreach ($response->data as $key => $response_data) { if (!get_user_meta($user_id, $response_data->id)) { From ff54c4bb1d2c71df66fa54496a01a6f187b52732 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Wed, 10 Jul 2019 09:16:20 +0530 Subject: [PATCH 27/99] Integrate volume tracking system, GFB-11 --- angelleye-gravity-forms-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index eeb98db..e7a1a79 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -46,7 +46,7 @@ // Require plugin entry point require_once $path . 'lib/class.plugify-gform-braintree.php'; - require_once $path . 'lib/angelleye-gravity-forms-payment-logger'; + require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; /** * Required functions From 9a302824e3331bf8505829694c36119a693974ac Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 11 Jul 2019 13:20:39 +0530 Subject: [PATCH 28/99] Notification System interval, GFB-9 --- lib/class.plugify-gform-braintree.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 1f8b6db..7725c64 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -317,10 +317,10 @@ public function get_plugin_settings () { public function angelleye_gform_braintree_display_push_notification() { global $current_user; $user_id = $current_user->ID; - if (false === ( $response = get_transient('angelleye_push_notification_result') )) { + if (false === ( $response = get_transient('angelleye_gravity_braintree_push_notification_result') )) { $response = $this->angelleye_get_push_notifications(); if(is_object($response)) { - set_transient('angelleye_push_notification_result', $response, 12 * HOUR_IN_SECONDS); + set_transient('angelleye_gravity_braintree_push_notification_result', $response, 12 * HOUR_IN_SECONDS); } } if (is_object($response)) { From f7b3c843bd2e593458df448d5a09b5aca8f1b5cc Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 12 Jul 2019 16:39:52 +0530 Subject: [PATCH 29/99] Updates changelog, GFB-9 --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index d39d43b..d8b366c 100644 --- a/readme.txt +++ b/readme.txt @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.1.3 - XX.XX.2019 = +* Tweak - Update push notification system sync interval time. ([GFB-9](https://github.com/angelleye/gravity-forms-braintree/pull/11)) + = 2.1.2 - 07.09.2019 = * Tweak - Minor adjustments to API request. From 52d0073482bc623fd773a28d3910313584c24336 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 18 Jul 2019 16:05:24 +0530 Subject: [PATCH 30/99] Integrate volume tracking system, GFB-11 --- lib/class.plugify-gform-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index ac81d8e..3c540cd 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,7 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - do_action('angelleye_gravity_forms_response_data', $$result, $submission_data, '1', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '1', ($settings['environment'] == 'Sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; From 151ea1c4cc22d9f71f96278e2d5a5f2aac804008 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 18 Jul 2019 16:08:13 +0530 Subject: [PATCH 31/99] Integrate volume tracking system, GFB-11 --- lib/class.plugify-gform-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 3c540cd..d1749bd 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,7 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '1', ($settings['environment'] == 'Sandbox') ? true : false , false, 'braintree'); + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '17', ($settings['environment'] == 'Sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; From 6d1dbd4bbb5f0d5a9480a531dc17fcea4cbbfec8 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 18 Jul 2019 16:17:45 +0530 Subject: [PATCH 32/99] Updates details for v2.1.3 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index ba96432..353b8a9 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.1.2 + * Version: 2.1.3 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/readme.txt b/readme.txt index d8b366c..0c99e65 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 Tested up to: 5.2.2 -Stable tag: 2.1.2 +Stable tag: 2.1.3 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.1.3 - XX.XX.2019 = += 2.1.3 - 07.18.2019 = * Tweak - Update push notification system sync interval time. ([GFB-9](https://github.com/angelleye/gravity-forms-braintree/pull/11)) = 2.1.2 - 07.09.2019 = From 79231fe23c5f090d2fcb60a79313a322650b3969 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Tue, 23 Jul 2019 14:33:20 +0530 Subject: [PATCH 33/99] Updates details for v2.1.3 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 0c99e65..e82b143 100644 --- a/readme.txt +++ b/readme.txt @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.1.3 - 07.18.2019 = += 2.1.3 - 07.23.2019 = * Tweak - Update push notification system sync interval time. ([GFB-9](https://github.com/angelleye/gravity-forms-braintree/pull/11)) = 2.1.2 - 07.09.2019 = From 55c9a00627918ae65dcfb560d486330c361c73b0 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Fri, 11 Oct 2019 16:15:17 +0530 Subject: [PATCH 34/99] Braintree field mapping added, GFB-12 --- angelleye-gravity-forms-braintree.php | 64 +++++-- assets/js/gravity-forms-braintree-admin.js | 32 ++++ ...elleye-gravity-braintree-field-mapping.php | 122 ++++++++++++++ .../angelleye-braintree-field-map-form.php | 156 ++++++++++++++++++ lib/class.plugify-gform-braintree.php | 16 +- 5 files changed, 364 insertions(+), 26 deletions(-) create mode 100644 includes/angelleye-gravity-braintree-field-mapping.php create mode 100644 includes/pages/angelleye-braintree-field-map-form.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 353b8a9..48d4034 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -33,28 +33,56 @@ } -$path = trailingslashit( dirname( __FILE__ ) ); +class AngelleyeGravityFormsBraintree{ + + protected static $instance = null; + public static $plugin_base_file; + + public static function getInstance() + { + self::$plugin_base_file = plugin_basename(__FILE__); + if(self::$instance==null) + self::$instance = new AngelleyeGravityFormsBraintree(); + + return self::$instance; + } -// Ensure Gravity Forms (payment addon framework) is installed and good to go -if( is_callable( array( 'GFForms', 'include_payment_addon_framework' ) ) ) { + public function __construct() + { + $this->init(); + } - // Bootstrap payment addon framework - GFForms::include_payment_addon_framework(); + public function init() + { + $path = trailingslashit( dirname( __FILE__ ) ); - // Require Braintree Payments core - require_once $path . 'lib/Braintree.php'; + // Ensure Gravity Forms (payment addon framework) is installed and good to go + if( is_callable( array( 'GFForms', 'include_payment_addon_framework' ) ) ) { - // Require plugin entry point - require_once $path . 'lib/class.plugify-gform-braintree.php'; + // Bootstrap payment addon framework + GFForms::include_payment_addon_framework(); - /** - * Required functions - */ - if (!function_exists('angelleye_queue_update')) { - require_once( 'includes/angelleye-functions.php' ); - } - - // Fire off entry point - new Plugify_GForm_Braintree(); + // Require Braintree Payments core + require_once $path . 'lib/Braintree.php'; + // Require plugin entry point + require_once $path . 'lib/class.plugify-gform-braintree.php'; + + require_once $path . 'includes/angelleye-gravity-braintree-field-mapping.php'; + + /** + * Required functions + */ + if (!function_exists('angelleye_queue_update')) { + require_once( 'includes/angelleye-functions.php' ); + } + + // Fire off entry point + new Plugify_GForm_Braintree(); + new AngelleyeGravityBraintreeFieldMapping(); + + } + } } + +AngelleyeGravityFormsBraintree::getInstance(); \ No newline at end of file diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index b42cd90..57104f8 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -18,4 +18,36 @@ jQuery(function () { }; jQuery.post(ajaxurl, param); } +}); + +jQuery(document).ready(function ($) { + $('.addmorecustomfield').click(function () { + $('.custom_field_row:last').after(''+$('.custom_fields_template').html()+' Remove '); + }); + + $('body').on('click','.remove_custom_field', function () { + $(this).closest('tr.custom_field_row') .remove(); + }); + + $('#gform_braintree_mapping').submit(function (e) { + e.preventDefault(); + + var data = $(this).serialize(); + var url = $(this).attr('action'); + + $.ajax({ + url:url, + method: 'post', + 'data': data, + 'dataType': 'json' + }).done(function (response) { + if(response.status){ + $('.successful_message').html('

'+response.message+'

') + }else { + console.log('error', response); + } + + }); + + }) }); \ No newline at end of file diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php new file mode 100644 index 0000000..b726975 --- /dev/null +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -0,0 +1,122 @@ +isCreditCardFieldExist($form_id)) { + $menu_items[] = array( + 'name' => 'braintree_mapping_settings_page', + 'label' => __('BrainTree Fields Mapping') + ); + } + } + return $menu_items; + } + + public function braintreeFieldMapping() + { + GFFormSettings::page_header(); + require dirname(__FILE__).'/pages/angelleye-braintree-field-map-form.php'; + GFFormSettings::page_footer(); + } + + public function isCreditCardFieldExist($id) + { + $get_form = GFAPI::get_form($id); + if(isset($get_form['fields'])) { + foreach ($get_form['fields'] as $single_field) { + if ($single_field->type == 'creditcard') { + return true; + } + } + } + return false; + } + + public function saveMapping() + { + $form_id = $_POST['gform_id']; + //sanitize input values + $final_mapping = []; + foreach ($_POST['gravity_form_field'] as $key=>$field_id){ + if(empty($field_id)) continue; + $final_mapping[$key] = $field_id; + } + + $custom_fields=[]; + if(isset($_POST['gravity_form_custom_field_name'])){ + $mapped_field_ids = $_POST['gravity_form_custom_field']; + foreach ($_POST['gravity_form_custom_field_name'] as $key => $single_custom_field_name){ + if(!isset($mapped_field_ids[$key]) || empty($mapped_field_ids[$key])) + continue; + + $custom_fields[$single_custom_field_name] = $mapped_field_ids[$key]; + } + } + if(count($custom_fields)) + $final_mapping['custom_fields'] = $custom_fields; + + $get_form = GFAPI::get_form($form_id); + $get_form['braintree_fields_mapping'] = $final_mapping; + GFAPI::update_form($get_form, $form_id); + + die(json_encode(['status'=>true,'message'=>'Mapping has been updated successfully.'])); + } + + function assignArrayByPath(&$arr, $path, $value, $separator='.') { + $keys = explode($separator, $path); + + foreach ($keys as $key) { + $arr = &$arr[$key]; + } + + $arr = $value; + } + + public function mapGravityBraintreeFields($args, $submission_data, $form, $entry) + { + + $braintree_mapping = isset($form['braintree_fields_mapping'])?$form['braintree_fields_mapping']:[]; + $final_array = []; + + if(count($braintree_mapping)){ + foreach ($braintree_mapping as $key_name => $single_mapid) + { + if(is_array($single_mapid)){ + if($key_name=='custom_fields') { + foreach ($single_mapid as $subkey_name => $sub_mapid) { + if (isset($entry[$sub_mapid])) { + $this->assignArrayByPath($final_array, 'customFields.' . $subkey_name, $entry[$sub_mapid]); + } + } + } + }else { + if (isset($entry[$single_mapid])) { + $this->assignArrayByPath($final_array, $key_name, $entry[$single_mapid]); + } + } + } + } + if(count($final_array)){ + $args = array_merge($args, $final_array); + } + //var_dump($args); die; + return $args; + } + +} diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php new file mode 100644 index 0000000..2653e34 --- /dev/null +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -0,0 +1,156 @@ + [ + 'company' => 'Company Name', + 'countryCodeAlpha2' => 'Country Code (e.g US)', + 'countryCodeAlpha3' => 'Country Code (e.g. USA)', + 'countryCodeNumeric' => 'Country Code (e.g. +1)', + 'countryName' => 'Country Name', + 'extendedAddress' => 'Apartment or Suite Number', + 'firstName' => 'First Name', + 'lastName' => 'Last Name', + 'locality' => 'Locality/City', + 'postalCode' => 'Postal Code', + 'region' => 'State/Province', + 'streetAddress' => 'Street Address', + ], + 'shipping' => [ + 'company' => 'Company Name', + 'countryCodeAlpha2' => 'Country Code (e.g US)', + 'countryCodeAlpha3' => 'Country Code (e.g. USA)', + 'countryCodeNumeric' => 'Country Code (e.g. +1)', + 'countryName' => 'Country Name', + 'extendedAddress' => 'Apartment or Suite Number', + 'firstName' => 'First Name', + 'lastName' => 'Last Name', + 'locality' => 'Locality/City', + 'postalCode' => 'Postal Code', + 'region' => 'State/Province', + 'streetAddress' => 'Street Address', + ], + //'customFields' => 'Custom Fields (Defined in your account)', + 'customer' => [ + 'company' => 'Company Name', + 'email' => 'Email', + 'firstName' => 'First Name', + 'lastName' => 'Last Name', + 'phone' => 'Phone', + 'website' => 'Website URL' + ] +]; + +$form_id = $_GET['id']; +$get_form = GFAPI::get_form($form_id); +//echo '
';print_r($get_form); die;
+
+$braintree_mapping = isset($get_form['braintree_fields_mapping'])?$get_form['braintree_fields_mapping']:[];
+
+function agreegateAllFields($main_arr, $parent_key = ''){
+    $final_fields = [];
+    foreach ($main_arr as $main_key => $single_field){
+        if(is_array($single_field))
+            $final_fields[$main_key] = agreegateAllFields($single_field, $main_key);
+        else {
+            $final_fields[($parent_key != '' ? $parent_key . '.' : '') . $main_key] = $single_field;
+        }
+    }
+
+    return $final_fields;
+}
+
+$total_braintree_fields = agreegateAllFields($braintree_fields);
+//print_r($total_braintree_fields);
+
+$gravity_fields = $get_form['fields'];
+$ignore_type_fields = ['creditcard'];
+
+$final_gravity_fields = [];
+foreach ($gravity_fields as $gravity_field) {
+    if(in_array($gravity_field->type, $ignore_type_fields))
+        continue;
+    $final_gravity_fields[$gravity_field['id']] = $gravity_field['label'];
+}
+//print_r($gravity_fields);
+?>
+

Braintree field Mapping

+

+ Please map the gravity form fields with Braintree fields +

+
+ + + + $single_field_set){ + if(is_array($single_field_set)){ + ?> + + + + $label){ + $selected_option = isset($braintree_mapping[$key])?$braintree_mapping[$key]:''; + ?> + + + + + + + + + + + + + + $mapped_id){ + ?> + + + + + + +

+ +
+ +

Custom Fields Add Custom Field

+ + Remove
+ +
+
+
+
+ +
+ \ No newline at end of file diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index e285aed..7f030ef 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -23,16 +23,13 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { */ public function __construct () { - add_action('wp_ajax_angelleye_gform_braintree_adismiss_notice', array($this, 'angelleye_gform_braintree_adismiss_notice'), 10); - add_action('admin_notices', array($this, 'angelleye_gform_braintree_display_push_notification'), 10); - - add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_css'), 10); - add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_js'), 10); + add_action('wp_ajax_angelleye_gform_braintree_adismiss_notice', array($this, 'angelleye_gform_braintree_adismiss_notice'), 10); + add_action('admin_notices', array($this, 'angelleye_gform_braintree_display_push_notification'), 10); + + add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_css'), 10); + add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_js'), 10); // Build parent parent::__construct(); - - - } /** @@ -101,6 +98,8 @@ public function authorize( $feed, $submission_data, $form, $entry ) { ) ); + $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); + try { // Configure Braintree environment @@ -116,6 +115,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { // Send transaction to Braintree $result = Braintree_Transaction::sale( $args ); + $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { From 3301bcb30dbd25a290f5f874e85736259ac45063 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Fri, 11 Oct 2019 16:17:25 +0530 Subject: [PATCH 35/99] Allow the addon to be enabled if Gravity form plugin is activated, Also disable when gravityform plugin is deactivated, GFB-14 --- angelleye-gravity-forms-braintree.php | 8 +++++ .../angelleye-gravity-braintree-activator.php | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100755 includes/angelleye-gravity-braintree-activator.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 48d4034..8c611b4 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -32,6 +32,7 @@ define('PAYPAL_FOR_WOOCOMMERCE_PUSH_NOTIFICATION_WEB_URL', 'https://www.angelleye.com/'); } +require_once dirname(__FILE__) . '/includes/angelleye-gravity-braintree-activator.php'; class AngelleyeGravityFormsBraintree{ @@ -49,6 +50,13 @@ public static function getInstance() public function __construct() { + register_activation_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,"InstallDb") ); + register_deactivation_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,"DeactivatePlugin") ); + register_uninstall_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,'Uninstall')); + + add_action( 'update_option_active_sitewide_plugins', array(AngelleyeGravityBraintreeActivator::class,'otherPluginDeactivated'), 10, 2 ); + add_action( 'update_option_active_plugins', array(AngelleyeGravityBraintreeActivator::class,'otherPluginDeactivated'), 10, 2 ); + $this->init(); } diff --git a/includes/angelleye-gravity-braintree-activator.php b/includes/angelleye-gravity-braintree-activator.php new file mode 100755 index 0000000..7e5b497 --- /dev/null +++ b/includes/angelleye-gravity-braintree-activator.php @@ -0,0 +1,35 @@ +« Return to Plugins'); + } + self::defaultPluginSetting(); + } + + public static function DeactivatePlugin(){ + + } + + public static function Uninstall(){ + + } + + public static function defaultPluginSetting(){ + + } + + public static function otherPluginDeactivated($plugin) + { + if(!is_plugin_active( 'gravityforms/gravityforms.php' ) || !class_exists('GFForms')){ + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + deactivate_plugins(AngelleyeGravityFormsBraintree::$plugin_base_file, true); + } + } +} \ No newline at end of file From 025054d7f82a4cf95b50de803173b28c8de5cfa8 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Fri, 11 Oct 2019 16:32:15 +0530 Subject: [PATCH 36/99] Payment logger logging issue resolved, variable passing issue and compare issue, GFB-13 --- lib/angelleye-gravity-forms-payment-logger.php | 2 +- lib/class.plugify-gform-braintree.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/angelleye-gravity-forms-payment-logger.php b/lib/angelleye-gravity-forms-payment-logger.php index 0da537e..43038a0 100644 --- a/lib/angelleye-gravity-forms-payment-logger.php +++ b/lib/angelleye-gravity-forms-payment-logger.php @@ -46,7 +46,7 @@ public function own_angelleye_gravity_forms_response_data($result_data, $request } else { $request_param['status'] = 'Failure'; } - if ($opt_in == 'yes') { + if ($opt_in_log == 'yes') { if (isset($result->transaction->statusHistory[0]->user) && !empty($result->transaction->statusHistory[0]->user)) { $request_param['merchant_id'] = $result->transaction->statusHistory[0]->user; } diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index e8ee573..6eecc4f 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,7 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - do_action('angelleye_gravity_forms_response_data', $$result, $submission_data, '1', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '1', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; From ee8d1ff3f233adf0b05f9ffe46a36340e7b60b2c Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Fri, 11 Oct 2019 16:33:22 +0530 Subject: [PATCH 37/99] Gitignore file added, GFB-13 --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62e7820 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Created by .ignore support plugin (hsz.mobi) +.idea \ No newline at end of file From 1325ed4b42f99ee72d91fbeb10c80519be270917 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Sat, 12 Oct 2019 03:32:42 +0530 Subject: [PATCH 38/99] Merchant id field error suppressed in case merchant id variable is not present in array, GFB-13 --- lib/angelleye-gravity-forms-payment-logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/angelleye-gravity-forms-payment-logger.php b/lib/angelleye-gravity-forms-payment-logger.php index 43038a0..8cd032a 100644 --- a/lib/angelleye-gravity-forms-payment-logger.php +++ b/lib/angelleye-gravity-forms-payment-logger.php @@ -68,7 +68,7 @@ public function angelleye_tpv_request($request_param) { $status = $request_param['status']; $site_url = $request_param['site_url']; $payment_mode = $request_param['mode']; - $merchant_id = $request_param['merchant_id']; + $merchant_id = @$request_param['merchant_id']; $correlation_id = $request_param['correlation_id']; $transaction_id = $request_param['transaction_id']; $product_id = $request_param['product_id']; From b1aaed605277f2c70112205629d7be1a112f46a1 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Sat, 12 Oct 2019 03:33:37 +0530 Subject: [PATCH 39/99] Gravity form multiple sub input support added for braintree field mapping, GFB-12 --- includes/pages/angelleye-braintree-field-map-form.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index 2653e34..f73dc83 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -9,10 +9,10 @@ 'extendedAddress' => 'Apartment or Suite Number', 'firstName' => 'First Name', 'lastName' => 'Last Name', + 'streetAddress' => 'Street Address', 'locality' => 'Locality/City', 'postalCode' => 'Postal Code', 'region' => 'State/Province', - 'streetAddress' => 'Street Address', ], 'shipping' => [ 'company' => 'Company Name', @@ -23,10 +23,10 @@ 'extendedAddress' => 'Apartment or Suite Number', 'firstName' => 'First Name', 'lastName' => 'Last Name', + 'streetAddress' => 'Street Address', 'locality' => 'Locality/City', 'postalCode' => 'Postal Code', 'region' => 'State/Province', - 'streetAddress' => 'Street Address', ], //'customFields' => 'Custom Fields (Defined in your account)', 'customer' => [ @@ -68,7 +68,11 @@ function agreegateAllFields($main_arr, $parent_key = ''){ foreach ($gravity_fields as $gravity_field) { if(in_array($gravity_field->type, $ignore_type_fields)) continue; - $final_gravity_fields[$gravity_field['id']] = $gravity_field['label']; + if(is_array($gravity_field['inputs']) && count($gravity_field['inputs'])){ + foreach ($gravity_field['inputs'] as $single_input) + $final_gravity_fields[$single_input['id']] = $single_input['label'].' ('.$gravity_field['label'].')'; + }else + $final_gravity_fields[$gravity_field['id']] = $gravity_field['label']; } //print_r($gravity_fields); ?> From 8624d54918160fce2e2303ef9c30a6a8e34f818f Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 11:38:15 +0530 Subject: [PATCH 40/99] Country code fields removed, Added notice on credit card form on edit form page, Updated form ui on mapping field page, GFB-12 --- assets/js/gravity-forms-braintree-admin.js | 5 ++++- ...elleye-gravity-braintree-field-mapping.php | 19 +++++++++++++++++++ .../angelleye-braintree-field-map-form.php | 10 +++++----- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index 57104f8..7ffc499 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -34,7 +34,8 @@ jQuery(document).ready(function ($) { var data = $(this).serialize(); var url = $(this).attr('action'); - + $('.successful_message').html(''); + $('.updatemappingbtn').html('Saving...').attr('disabled','disabled'); $.ajax({ url:url, method: 'post', @@ -47,6 +48,8 @@ jQuery(document).ready(function ($) { console.log('error', response); } + }).complete(function () { + $('.updatemappingbtn').html('Update Mapping').removeAttr('disabled'); }); }) diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index b726975..264b3c9 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -13,6 +13,8 @@ public function __construct() add_action('wp_ajax_save_gravity_form_mapping', array($this,'saveMapping')); add_filter('angelleye_braintree_parameter', array($this, 'mapGravityBraintreeFields'),10, 4); + + add_filter( 'gform_field_content', array($this,'addNoticeToCreditCardForm'), 10, 5 ); } public function addBraintreeMappingMenu($menu_items, $form_id) @@ -119,4 +121,21 @@ public function mapGravityBraintreeFields($args, $submission_data, $form, $entry return $args; } + function addNoticeToCreditCardForm( $field_content, $field, $value, $lead_id, $form_id ) { + if ( $field->type == 'creditcard' ) { + //echo ($field_content); die; + $first_label_position = strpos($field_content, ''settings', 'subview' => 'braintree_mapping_settings_page', 'id' => $form_id ], menu_page_url('gf_edit_forms', false)); + $feed_page_link = add_query_arg(['view'=>'settings', 'subview' => 'gravity-forms-braintree', 'id' => $form_id ], menu_page_url('gf_edit_forms', false)); + $field_content = substr_replace($field_content, + "

1) You can use Braintree Fields Mapping to send the values with transaction.
2) To process the payments, please configure the Braintree feed.

", + $first_label_position, 0); + } + } + + return $field_content; + } + } diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index f73dc83..2708fa4 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -2,9 +2,9 @@ $braintree_fields = [ 'billing' => [ 'company' => 'Company Name', - 'countryCodeAlpha2' => 'Country Code (e.g US)', + /*'countryCodeAlpha2' => 'Country Code (e.g US)', 'countryCodeAlpha3' => 'Country Code (e.g. USA)', - 'countryCodeNumeric' => 'Country Code (e.g. +1)', + 'countryCodeNumeric' => 'Country Code (e.g. +1)',*/ 'countryName' => 'Country Name', 'extendedAddress' => 'Apartment or Suite Number', 'firstName' => 'First Name', @@ -16,9 +16,9 @@ ], 'shipping' => [ 'company' => 'Company Name', - 'countryCodeAlpha2' => 'Country Code (e.g US)', + /*'countryCodeAlpha2' => 'Country Code (e.g US)', 'countryCodeAlpha3' => 'Country Code (e.g. USA)', - 'countryCodeNumeric' => 'Country Code (e.g. +1)', + 'countryCodeNumeric' => 'Country Code (e.g. +1)',*/ 'countryName' => 'Country Name', 'extendedAddress' => 'Apartment or Suite Number', 'firstName' => 'First Name', @@ -139,7 +139,7 @@ function agreegateAllFields($main_arr, $parent_key = ''){ - +
From b9fdeddc27fce890ee9fba41f9532e607df8a02f Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 11:44:16 +0530 Subject: [PATCH 41/99] Volume tracker plugin id updated, GFB-13 --- lib/class.plugify-gform-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 6eecc4f..cf228ca 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,7 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '1', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; From 6fbbd3c86a753be32384c3b18fd5d360828040a4 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 12:40:24 +0530 Subject: [PATCH 42/99] Added notice on Braintree field mapping page and fixed it to display on admin, GFB-13 --- ...elleye-gravity-braintree-field-mapping.php | 31 ++++++++++++------- .../angelleye-braintree-field-map-form.php | 10 ++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index 264b3c9..03639b4 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -122,19 +122,28 @@ public function mapGravityBraintreeFields($args, $submission_data, $form, $entry } function addNoticeToCreditCardForm( $field_content, $field, $value, $lead_id, $form_id ) { - if ( $field->type == 'creditcard' ) { - //echo ($field_content); die; - $first_label_position = strpos($field_content, ''settings', 'subview' => 'braintree_mapping_settings_page', 'id' => $form_id ], menu_page_url('gf_edit_forms', false)); - $feed_page_link = add_query_arg(['view'=>'settings', 'subview' => 'gravity-forms-braintree', 'id' => $form_id ], menu_page_url('gf_edit_forms', false)); - $field_content = substr_replace($field_content, - "

1) You can use Braintree Fields Mapping to send the values with transaction.
2) To process the payments, please configure the Braintree feed.

", - $first_label_position, 0); + if(is_admin()) { + if ($field->type == 'creditcard') { + //echo ($field_content); die; + $first_label_position = strpos($field_content, ' 'settings', + 'subview' => 'braintree_mapping_settings_page', + 'id' => $form_id + ], menu_page_url('gf_edit_forms', false)); + $feed_page_link = add_query_arg([ + 'view' => 'settings', + 'subview' => 'gravity-forms-braintree', + 'id' => $form_id + ], menu_page_url('gf_edit_forms', false)); + $field_content = substr_replace($field_content, + "

1) You can use Braintree Fields Mapping to send the values with transaction.
2) To process the payments, please configure the Braintree feed.

", + $first_label_position, 0); + } } } - return $field_content; } diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index 2708fa4..dd45577 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -77,6 +77,16 @@ function agreegateAllFields($main_arr, $parent_key = ''){ //print_r($gravity_fields); ?>

Braintree field Mapping

+ + 'settings', + 'subview' => 'gravity-forms-braintree', + 'id' => $form_id +], menu_page_url('gf_edit_forms', false)); + +echo "

Please make sure to configure the Braintree feed to process the payments.

"; ?> +

Please map the gravity form fields with Braintree fields

From 93d9f87395b9c055afad34d0df27c7c020797e31 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 12:41:33 +0530 Subject: [PATCH 43/99] Fixed the sandbox and live mode condition check, GFB-13 --- lib/class.plugify-gform-braintree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index cf228ca..f4073c0 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -119,7 +119,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment if( $result->success == '1' ) { - do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', ($settings['environment'] == 'sandbox') ? true : false , false, 'braintree'); + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; $authorization['transaction_id'] = $result->transaction->id; From edddcd2b7e70c5504481243dee30551e6563f719 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 19:08:41 +0530 Subject: [PATCH 44/99] Verbiage updated for the field mapping and notices, GFB-12 --- angelleye-gravity-forms-braintree.php | 9 ++++++ ...elleye-gravity-braintree-field-mapping.php | 28 +++++++++++++------ .../angelleye-braintree-field-map-form.php | 14 ++++++---- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 48d4034..6629b90 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -83,6 +83,15 @@ public function init() } } + + public static function isBraintreeFeedActive() + { + global $wpdb; + $addon_feed_table_name = $wpdb->prefix . 'gf_addon_feed'; + $is_active = $wpdb->get_var("select is_active from ".$addon_feed_table_name." where addon_slug='gravity-forms-braintree' and is_active=1"); + + return $is_active=='1'; + } } AngelleyeGravityFormsBraintree::getInstance(); \ No newline at end of file diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index 03639b4..fe5ba43 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -127,20 +127,30 @@ function addNoticeToCreditCardForm( $field_content, $field, $value, $lead_id, $ //echo ($field_content); die; $first_label_position = strpos($field_content, ' 'settings', 'subview' => 'braintree_mapping_settings_page', 'id' => $form_id ], menu_page_url('gf_edit_forms', false)); - $feed_page_link = add_query_arg([ - 'view' => 'settings', - 'subview' => 'gravity-forms-braintree', - 'id' => $form_id - ], menu_page_url('gf_edit_forms', false)); - $field_content = substr_replace($field_content, - "

1) You can use Braintree Fields Mapping to send the values with transaction.
2) To process the payments, please configure the Braintree feed.

", - $first_label_position, 0); + + if(!AngelleyeGravityFormsBraintree::isBraintreeFeedActive()) { + $feed_page_link = add_query_arg([ + 'view' => 'settings', + 'subview' => 'gravity-forms-braintree', + 'id' => $form_id + ], menu_page_url('gf_edit_forms', false)); + $add_text[] = "To process payments, please configure a Braintree feed."; + } + + $add_text[] = "You can use Braintree Field Mapping to pass specific data values into the Braintree transaction details."; + $final_text = ''; + foreach ($add_text as $key=>$single_text){ + $final_text.=($final_text!=''?'
':'').($key+1).") ".$single_text; + } + $replacement_text = "

$final_text

"; + + $field_content = substr_replace($field_content,$replacement_text, $first_label_position, 0); } } } diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index dd45577..ea4e596 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -79,13 +79,15 @@ function agreegateAllFields($main_arr, $parent_key = ''){

Braintree field Mapping

'settings', - 'subview' => 'gravity-forms-braintree', - 'id' => $form_id -], menu_page_url('gf_edit_forms', false)); +if(!AngelleyeGravityFormsBraintree::isBraintreeFeedActive()) { + $feed_page_link = add_query_arg([ + 'view' => 'settings', + 'subview' => 'gravity-forms-braintree', + 'id' => $form_id + ], menu_page_url('gf_edit_forms', false)); -echo "

Please make sure to configure the Braintree feed to process the payments.

"; ?> + echo "

Please make sure to configure the Braintree feed to process the payments.

"; +}?>

Please map the gravity form fields with Braintree fields From fcdfdcfba7a8c0cb954ec0f26bcea29dd433e4f6 Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 19:33:55 +0530 Subject: [PATCH 45/99] Added help section on mapping field page, GFB-12 --- includes/angelleye-gravity-braintree-field-mapping.php | 2 +- includes/pages/angelleye-braintree-field-map-form.php | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index fe5ba43..ae4d344 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -23,7 +23,7 @@ public function addBraintreeMappingMenu($menu_items, $form_id) if($this->isCreditCardFieldExist($form_id)) { $menu_items[] = array( 'name' => 'braintree_mapping_settings_page', - 'label' => __('BrainTree Fields Mapping') + 'label' => __('Braintree Field Mapping') ); } } diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index ea4e596..5d8de49 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -76,7 +76,7 @@ function agreegateAllFields($main_arr, $parent_key = ''){ } //print_r($gravity_fields); ?> -

Braintree field Mapping

+

Braintree Field Mapping

- Please map the gravity form fields with Braintree fields + Here you can map individual Gravity form fields to Braintree fields so that they will show up in the Braintree transaction details.

+

The field names on the left are currently available in Braintree. Simply select the Gravity form field from the drop-down that you would like to pass to the matching field in Braintree transaction details.

+

If you do not see a Braintree field available for your Gravity form field, you may create custom fields within your Braintree account, and then add these custom fields at the bottom of this field mapping section.

+

For more information, see our documentation.

From 7c630b53fb5adc3a81f73e52603eed5d0d5617cc Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Wed, 16 Oct 2019 19:42:24 +0530 Subject: [PATCH 46/99] Field order updated on the field mapping page, GFB-12 --- .../angelleye-braintree-field-map-form.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index 5d8de49..3630df1 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -1,39 +1,39 @@ [ - 'company' => 'Company Name', + 'firstName' => 'First Name', + 'lastName' => 'Last Name', + 'company' => 'Company Name', /*'countryCodeAlpha2' => 'Country Code (e.g US)', 'countryCodeAlpha3' => 'Country Code (e.g. USA)', 'countryCodeNumeric' => 'Country Code (e.g. +1)',*/ - 'countryName' => 'Country Name', - 'extendedAddress' => 'Apartment or Suite Number', - 'firstName' => 'First Name', - 'lastName' => 'Last Name', 'streetAddress' => 'Street Address', + 'extendedAddress' => 'Street Address 2 (Apartment or Suite Number)', 'locality' => 'Locality/City', - 'postalCode' => 'Postal Code', 'region' => 'State/Province', + 'postalCode' => 'Postal Code', + 'countryName' => 'Country Name', ], 'shipping' => [ - 'company' => 'Company Name', + 'firstName' => 'First Name', + 'lastName' => 'Last Name', + 'company' => 'Company Name', /*'countryCodeAlpha2' => 'Country Code (e.g US)', 'countryCodeAlpha3' => 'Country Code (e.g. USA)', 'countryCodeNumeric' => 'Country Code (e.g. +1)',*/ - 'countryName' => 'Country Name', - 'extendedAddress' => 'Apartment or Suite Number', - 'firstName' => 'First Name', - 'lastName' => 'Last Name', 'streetAddress' => 'Street Address', + 'extendedAddress' => 'Street Address 2 (Apartment or Suite Number)', 'locality' => 'Locality/City', - 'postalCode' => 'Postal Code', 'region' => 'State/Province', + 'postalCode' => 'Postal Code', + 'countryName' => 'Country Name', ], //'customFields' => 'Custom Fields (Defined in your account)', 'customer' => [ - 'company' => 'Company Name', - 'email' => 'Email', 'firstName' => 'First Name', 'lastName' => 'Last Name', + 'company' => 'Company Name', + 'email' => 'Email', 'phone' => 'Phone', 'website' => 'Website URL' ] From 01830a9bca3764f2f4cf8a4caf8b6e656959ea67 Mon Sep 17 00:00:00 2001 From: angelleye Date: Wed, 16 Oct 2019 09:55:09 -0500 Subject: [PATCH 47/99] Updates changelog --- readme.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.txt b/readme.txt index e82b143..18da80b 100644 --- a/readme.txt +++ b/readme.txt @@ -64,6 +64,10 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.2.0 = 10.16.2019 = +* Feature - Adds Braintree field mapping capability. ([GFB-12](https://github.com/angelleye/gravity-forms-braintree/pull/14)) +* Tweak - Adds a notice if you try to activate the Braintree Payments extension without Gravity Forms active. + = 2.1.3 - 07.23.2019 = * Tweak - Update push notification system sync interval time. ([GFB-9](https://github.com/angelleye/gravity-forms-braintree/pull/11)) From 1fdf8e797022c0b29fc23ab0321428e566096bdd Mon Sep 17 00:00:00 2001 From: angelleye Date: Wed, 16 Oct 2019 09:57:46 -0500 Subject: [PATCH 48/99] Updates tested up to version --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 18da80b..f3fc533 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.2.2 +Tested up to: 5.2.4 Stable tag: 2.1.3 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From 00e8561e5a17b4499ce45288ee9961a664d98e46 Mon Sep 17 00:00:00 2001 From: angelleye Date: Wed, 16 Oct 2019 10:03:00 -0500 Subject: [PATCH 49/99] Updates version details for v2.2.0 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index a7a939f..7d9f9e7 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.1.3 + * Version: 2.2.0 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/readme.txt b/readme.txt index f3fc533..b90f652 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 Tested up to: 5.2.4 -Stable tag: 2.1.3 +Stable tag: 2.2.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From cd3f99db7698825f1d553bfcd16f6cd1c4848ffb Mon Sep 17 00:00:00 2001 From: deepakmaurya Date: Tue, 22 Oct 2019 21:33:33 +0530 Subject: [PATCH 50/99] Fixed UI issues for small width screens, GFB-15 --- assets/js/gravity-forms-braintree-admin.js | 2 +- .../pages/angelleye-braintree-field-map-form.php | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index 7ffc499..c13f21b 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -22,7 +22,7 @@ jQuery(function () { jQuery(document).ready(function ($) { $('.addmorecustomfield').click(function () { - $('.custom_field_row:last').after(''); + $('.custom_field_row:last').after(''); }); $('body').on('click','.remove_custom_field', function () { diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index 3630df1..781019c 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -137,13 +137,13 @@ function agreegateAllFields($main_arr, $parent_key = ''){ - + $mapped_id){ ?> - - + '); + if($('.custom_field_row').length>1){ + $('.alert-notification-custom-fields').removeClass('hide'); + } }); $('body').on('click','.remove_custom_field', function () { diff --git a/includes/pages/angelleye-braintree-field-map-form.php b/includes/pages/angelleye-braintree-field-map-form.php index 781019c..4992234 100644 --- a/includes/pages/angelleye-braintree-field-map-form.php +++ b/includes/pages/angelleye-braintree-field-map-form.php @@ -137,7 +137,24 @@ function agreegateAllFields($main_arr, $parent_key = ''){ - + + + $mapped_id){ diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 5736021..d9fe9f9 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -28,6 +28,8 @@ public function __construct () { add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_css'), 10); add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_js'), 10); + add_filter( 'gform_noconflict_scripts', [$this, 'include_angelleye_braintree_script_noconflict'] ); + add_filter( 'gform_noconflict_styles', [$this, 'include_angelleye_braintree_style_noconflict'] ); // Build parent parent::__construct(); } @@ -385,12 +387,26 @@ public function angelleye_gform_braintree_adismiss_notice() { } } + public function include_angelleye_braintree_style_noconflict( $styles ) { + $styles[] = 'gravity-forms-braintree-admin-css'; + return $styles; + } + + public function include_angelleye_braintree_script_noconflict( $scripts ) { + $scripts[] = 'gravity-forms-braintree-admin'; + return $scripts; + } + public function enqueue_scripts_js() { - wp_enqueue_script('gravity-forms-braintree-admin', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/gravity-forms-braintree-admin.js', array('jquery'), $this->_version, false); + if(GFForms::is_gravity_page()) { + wp_enqueue_script( 'gravity-forms-braintree-admin', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/gravity-forms-braintree-admin.js', array( 'jquery' ), $this->_version, false ); + } } public function enqueue_styles_css() { - wp_enqueue_style('gravity-forms-braintree-admin-css', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/css/gravity-forms-braintree-admin.css', array(), $this->_version, 'all'); + if(GFForms::is_gravity_page()) { + wp_enqueue_style( 'gravity-forms-braintree-admin-css', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/css/gravity-forms-braintree-admin.css', array(), $this->_version, 'all' ); + } } } \ No newline at end of file From 58aa7a1f1aa08ef1aef19017456ee0549fea7107 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 28 Apr 2020 19:48:35 +0530 Subject: [PATCH 62/99] Updates Version Details & Changelog for v3.0.0 --- angelleye-gravity-forms-braintree.php | 2 +- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 8e19f9b..cc08750 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.2.2 + * Version: 3.0.0 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index b25fbd1..47c00b0 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '2.2.2'; + protected $_version = '3.0.0'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index b3bcc5f..7f98e01 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 Tested up to: 5.3.2 -Stable tag: 2.2.2 +Stable tag: 3.0.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,6 +64,10 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.0.0 - 04.28.2020 = +* Upgrade - Braintree Library Upgraded from 3.36.0 to 5.0.0 ([GFB-18](https://github.com/angelleye/gravity-forms-braintree/pull/21)) +* Tweak - Support Gravity Form No Conflict Mode issue with Braintree script loading in backend. ([GFB-19](https://github.com/angelleye/gravity-forms-braintree/pull/20)) + = 2.2.2 - 12.30.2019 = * Tweak - Adjustment to Updater plugin notice dismissible. ([GFB-16](https://github.com/angelleye/gravity-forms-braintree/pull/17)) From e64f968ad916b8d48f9a5723caf2c9b1951824df Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 28 Apr 2020 20:45:46 +0530 Subject: [PATCH 63/99] Fatal error resolved with Conditional Braintree library loading, Compatibility issue with PFW, GFB-18 --- angelleye-gravity-forms-braintree.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 8e19f9b..f94ce65 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -71,7 +71,9 @@ public function init() GFForms::include_payment_addon_framework(); // Require Braintree Payments core - require_once $path . 'lib/Braintree.php'; + if(!class_exists('Braintree')) { + require_once $path . 'lib/Braintree.php'; + } // Require plugin entry point require_once $path . 'lib/class.plugify-gform-braintree.php'; From a0249ffccb017bfce1716a845ebaa44fe9ce9dc8 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 28 Apr 2020 20:53:21 +0530 Subject: [PATCH 64/99] Updates Version Details & Changelog for v3.0.1 --- angelleye-gravity-forms-braintree.php | 2 +- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 53dc2cf..f623f0b 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.0.0 + * Version: 3.0.1 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 47c00b0..60a2576 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '3.0.0'; + protected $_version = '3.0.1'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index 7f98e01..94e4a53 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 Tested up to: 5.3.2 -Stable tag: 3.0.0 +Stable tag: 3.0.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.0.1 - 04.28.2020 = +* Fix - Compatibility issue with PayPal for WooCommerce in loading Braintree library ([GFB-18](https://github.com/angelleye/gravity-forms-braintree/pull/22)) + = 3.0.0 - 04.28.2020 = * Upgrade - Braintree Library Upgraded from 3.36.0 to 5.0.0 ([GFB-18](https://github.com/angelleye/gravity-forms-braintree/pull/21)) * Tweak - Support Gravity Form No Conflict Mode issue with Braintree script loading in backend. ([GFB-19](https://github.com/angelleye/gravity-forms-braintree/pull/20)) From 5db0c8cbf56bc369287f8a067bcbc63c759db200 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Mon, 4 May 2020 11:46:22 +0530 Subject: [PATCH 65/99] PHP version check Braintree exception issue resolved --- lib/Braintree.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Braintree.php b/lib/Braintree.php index 6a984c7..63fbb73 100644 --- a/lib/Braintree.php +++ b/lib/Braintree.php @@ -7,7 +7,7 @@ require_once(__DIR__ . DIRECTORY_SEPARATOR . 'autoload.php'); if (version_compare(PHP_VERSION, '7.2.0', '<')) { - throw new Braintree_Exception('PHP version >= 7.2.0 required'); + throw new \Braintree\Exception('PHP version >= 7.2.0 required'); } class Braintree { @@ -15,7 +15,7 @@ public static function requireDependencies() { $requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl']; foreach ($requiredExtensions AS $ext) { if (!extension_loaded($ext)) { - throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.'); + throw new \Braintree\Exception('The Braintree library requires the ' . $ext . ' extension.'); } } } From b10218531c8f6b5b32b74c8de84ec8f061ae9c93 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Mon, 4 May 2020 12:16:36 +0530 Subject: [PATCH 66/99] Version & Changelog Updates for v3.0.2 --- angelleye-gravity-forms-braintree.php | 2 +- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index f623f0b..46e3672 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.0.1 + * Version: 3.0.2 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 60a2576..7bb42ee 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '3.0.1'; + protected $_version = '3.0.2'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index 94e4a53..eba0ecd 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 Tested up to: 5.3.2 -Stable tag: 3.0.1 +Stable tag: 3.0.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.0.2 - 05.04.2020 = +* Fix - Resolved the issue with PHP Version comparison ([GFB-21](https://github.com/angelleye/gravity-forms-braintree/pull/23)) + = 3.0.1 - 04.28.2020 = * Fix - Compatibility issue with PayPal for WooCommerce in loading Braintree library ([GFB-18](https://github.com/angelleye/gravity-forms-braintree/pull/22)) From ea86bf4f60eb863d3a4e66989c8f522f832aacc4 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Sun, 10 May 2020 02:17:26 +0530 Subject: [PATCH 67/99] Plugin requirement check feature updated to show notice and deactivate plugin, GFB-22 --- angelleye-gravity-forms-braintree.php | 66 ++++---- .../angelleye-gravity-braintree-activator.php | 11 -- .../angelleye-plugin-requirement-checker.php | 145 ++++++++++++++++++ lib/Braintree.php | 16 -- 4 files changed, 184 insertions(+), 54 deletions(-) create mode 100644 includes/angelleye-plugin-requirement-checker.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 46e3672..e857645 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -33,11 +33,13 @@ } require_once dirname(__FILE__) . '/includes/angelleye-gravity-braintree-activator.php'; +require_once dirname(__FILE__) . '/includes/angelleye-plugin-requirement-checker.php'; class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; + public static $version = '3.0.2'; public static function getInstance() { @@ -54,45 +56,55 @@ public function __construct() register_deactivation_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,"DeactivatePlugin") ); register_uninstall_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,'Uninstall')); - add_action( 'update_option_active_sitewide_plugins', array(AngelleyeGravityBraintreeActivator::class,'otherPluginDeactivated'), 10, 2 ); - add_action( 'update_option_active_plugins', array(AngelleyeGravityBraintreeActivator::class,'otherPluginDeactivated'), 10, 2 ); + add_action('plugins_loaded', [$this, 'requirementCheck']); + } - $this->init(); + public function requirementCheck() { + $checker = new Angelleye_Plugin_Requirement_Checker('Gravity Forms Braintree Payments', self::$version, self::$plugin_base_file); + $checker->setPHP('7.2'); + $checker->setRequiredClasses(['GFForms' => 'Gravity forms plugin is required to run the Gravity Forms Braintree.']); + $checker->setRequiredExtensions(['xmlwriter', 'openssl', 'dom', 'hash', 'curl']); + $checker->setRequiredPlugins(['gravityforms/gravityforms.php'=>'2.4']); + $checker->setDeactivatePlugins([self::$plugin_base_file]); + if($checker->check()===true) { + $this->init(); + } } public function init() { - $path = trailingslashit( dirname( __FILE__ ) ); + $path = trailingslashit( dirname( __FILE__ ) ); + + // Ensure Gravity Forms (payment addon framework) is installed and good to go + if ( is_callable( array( 'GFForms', 'include_payment_addon_framework' ) ) ) { - // Ensure Gravity Forms (payment addon framework) is installed and good to go - if( is_callable( array( 'GFForms', 'include_payment_addon_framework' ) ) ) { + // Bootstrap payment addon framework + GFForms::include_payment_addon_framework(); - // Bootstrap payment addon framework - GFForms::include_payment_addon_framework(); + // Require Braintree Payments core + if ( ! class_exists( 'Braintree' ) ) { + require_once $path . 'lib/Braintree.php'; + } - // Require Braintree Payments core - if(!class_exists('Braintree')) { - require_once $path . 'lib/Braintree.php'; - } + // Require plugin entry point + require_once $path . 'lib/class.plugify-gform-braintree.php'; + require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; + require_once $path . 'includes/angelleye-gravity-braintree-field-mapping.php'; - // Require plugin entry point - require_once $path . 'lib/class.plugify-gform-braintree.php'; - require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; - require_once $path . 'includes/angelleye-gravity-braintree-field-mapping.php'; + /** + * Required functions + */ + if ( ! function_exists( 'angelleye_queue_update' ) ) { + require_once( 'includes/angelleye-functions.php' ); + } - /** - * Required functions - */ - if (!function_exists('angelleye_queue_update')) { - require_once( 'includes/angelleye-functions.php' ); - } + // Fire off entry point + new Plugify_GForm_Braintree(); + new AngelleyeGravityBraintreeFieldMapping(); + AngellEYE_GForm_Braintree_Payment_Logger::instance(); - // Fire off entry point - new Plugify_GForm_Braintree(); - new AngelleyeGravityBraintreeFieldMapping(); - AngellEYE_GForm_Braintree_Payment_Logger::instance(); + } - } } public static function isBraintreeFeedActive() diff --git a/includes/angelleye-gravity-braintree-activator.php b/includes/angelleye-gravity-braintree-activator.php index 7e5b497..d7524f2 100755 --- a/includes/angelleye-gravity-braintree-activator.php +++ b/includes/angelleye-gravity-braintree-activator.php @@ -7,9 +7,6 @@ public static function InstallDb(){ global $wpdb; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); - if ( ! is_plugin_active( 'gravityforms/gravityforms.php' ) ) { - wp_die('This plugin requires gravity form to be installed and active.
« Return to Plugins'); - } self::defaultPluginSetting(); } @@ -24,12 +21,4 @@ public static function Uninstall(){ public static function defaultPluginSetting(){ } - - public static function otherPluginDeactivated($plugin) - { - if(!is_plugin_active( 'gravityforms/gravityforms.php' ) || !class_exists('GFForms')){ - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); - deactivate_plugins(AngelleyeGravityFormsBraintree::$plugin_base_file, true); - } - } } \ No newline at end of file diff --git a/includes/angelleye-plugin-requirement-checker.php b/includes/angelleye-plugin-requirement-checker.php new file mode 100644 index 0000000..286edb4 --- /dev/null +++ b/includes/angelleye-plugin-requirement-checker.php @@ -0,0 +1,145 @@ +plugin_name = $plugin_name; + $this->plugin_version = $plugin_version; + $this->base_plugin_file = $base_plugin_file; + $this->plugin_check_option_name = sanitize_title($this->plugin_name.'-'.$this->plugin_version); + + //add_action( 'update_option_active_sitewide_plugins', [$this, 'checkPluginDeactivation'], 10, 2 ); + //add_action( 'update_option_active_plugins', [$this, 'checkPluginDeactivation'], 10, 2 ); + } + + public function setDeactivatePlugins( $plugin_basenames = [] ) { + $this->deactivate_plugins = array_merge($this->deactivate_plugins, $plugin_basenames); + } + + /** + * Accepts a key value array, where key defines the plugin name and value defines the min version required + * @param array $classes + */ + public function setRequiredPlugins( $plugin_names = [] ) { + $this->required_plugins = array_merge($this->required_plugins, $plugin_names); + } + + /** + * Accepts a key value array, where key defines the class name and value defines the error message + * @param array $classes + */ + public function setRequiredClasses( $classes = [] ) { + $this->required_classes = array_merge($this->required_classes, $classes); + } + + /** + * Accepts a version string to check + * @param $version_required + */ + public function setPHP( $version_required ) { + if (version_compare(PHP_VERSION, $version_required, '<')) { + $this->errors_list['VERSION_PHP'] = __('PHP version >= '.$version_required.' is required to run '. $this->plugin_name); + } + } + + public function setRequiredExtensions( $extensions ) { + $this->required_extensions = array_merge($this->required_extensions, $extensions); + } + + public function check( $force_check = false ) { + $check = get_option($this->plugin_check_option_name); + if($check=='passed' && !$force_check) + return true; + + if(count($this->required_classes)){ + foreach ($this->required_classes as $class_name => $class_msg){ + if(!class_exists($class_name)) + $this->errors_list['CLASS_'.$class_name] = $class_msg; + } + } + + if(count($this->required_plugins)){ + $all_plugins = get_plugins(); + $active_plugins = get_option('active_plugins'); + foreach ($this->required_plugins as $single_plugin => $min_version_required){ + if(in_array($single_plugin, $active_plugins)){ + if(version_compare($all_plugins[$single_plugin]['Version'], $min_version_required, '<')){ + $this->errors_list[] = 'You have '.$all_plugins[$single_plugin]['Name'].' - Version: '.$all_plugins[$single_plugin]['Version'].' active, we require min '.$all_plugins[$single_plugin]['Name'].' - Version: '.$min_version_required.' to run the '.$this->plugin_name; + } + }else if(isset($all_plugins[$single_plugin])) { + $this->errors_list[] = 'Please activate '.$all_plugins[$single_plugin]['Name'].' plugin to run the '.$this->plugin_name; + } else{ + $this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.'; + } + } + /*echo '
';
+				print_r($all_plugins);
+				print_r($active_plugins);die;*/
+
+			}
+
+			if(count($this->required_extensions)) {
+				$ext_error = [];
+				foreach ( $this->required_extensions AS $ext ) {
+					if ( ! extension_loaded( $ext ) ) {
+						$ext_error[] = $ext;
+					}
+				}
+				if(count($ext_error)){
+					$this->errors_list[] = implode(', ', $ext_error).' extensions are required for the '.$this->plugin_name;
+				}
+			}
+			
+			if(count($this->errors_list)){
+				add_action('admin_notices', [$this, 'showAdminNotice']);
+				delete_option($this->plugin_check_option_name);
+				return $this->errors_list;
+			}else {
+				update_option($this->plugin_check_option_name, 'passed');
+				return true;
+			}
+		}
+
+		public function showAdminNotice(  ) {
+
+			echo '
+

'.(in_array($this->base_plugin_file, $this->deactivate_plugins)? + $this->plugin_name.' plugin has been deactivated due to following errors.': + $this->plugin_name.' plugin is inactive due to following errors.').'

+

'.implode('
', $this->errors_list).'

+
'; + if(count($this->deactivate_plugins)){ + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + foreach ($this->deactivate_plugins as $single_plugin_basename){ + if ( is_plugin_active( $single_plugin_basename ) ) { + deactivate_plugins( $single_plugin_basename ); + } + } + if ( isset( $_GET['activate'] ) ) { + unset( $_GET['activate'] ); + } + } + } + + public function checkPluginDeactivation( $new_value, $old_value ) { + if($this->check(true)!== true){ + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + foreach ($this->deactivate_plugins as $single_plugin_basename) + deactivate_plugins($single_plugin_basename, true); + } + } + } +} \ No newline at end of file diff --git a/lib/Braintree.php b/lib/Braintree.php index 63fbb73..1690af9 100644 --- a/lib/Braintree.php +++ b/lib/Braintree.php @@ -6,19 +6,3 @@ require_once(__DIR__ . DIRECTORY_SEPARATOR . 'autoload.php'); -if (version_compare(PHP_VERSION, '7.2.0', '<')) { - throw new \Braintree\Exception('PHP version >= 7.2.0 required'); -} - -class Braintree { - public static function requireDependencies() { - $requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl']; - foreach ($requiredExtensions AS $ext) { - if (!extension_loaded($ext)) { - throw new \Braintree\Exception('The Braintree library requires the ' . $ext . ' extension.'); - } - } - } -} - -Braintree::requireDependencies(); From 4f1b6a28f44cab662572348b1c799720fb743fce Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 12 May 2020 02:15:14 +0530 Subject: [PATCH 68/99] Integrated Braintree ACH Direct Debit Payment Method with Payment Method Toggle Field, GFB-17 --- angelleye-gravity-forms-braintree.php | 12 +- assets/js/angelleye-braintree-ach-cc.js | 192 ++++++++ ...elleye-gravity-braintree-field-mapping.php | 2 +- .../angelleye-gravity-braintree-helper.php | 49 ++ ...-angelleye-gravity-braintree-ach-field.php | 422 ++++++++++++++++++ ...eye-gravity-braintree-ach-toggle-field.php | 136 ++++++ lib/class.plugify-gform-braintree.php | 328 +++++++++++++- 7 files changed, 1128 insertions(+), 13 deletions(-) create mode 100644 assets/js/angelleye-braintree-ach-cc.js create mode 100644 includes/angelleye-gravity-braintree-helper.php create mode 100644 includes/class-angelleye-gravity-braintree-ach-field.php create mode 100644 includes/class-angelleye-gravity-braintree-ach-toggle-field.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 46e3672..7c2c017 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -69,6 +69,7 @@ public function init() // Bootstrap payment addon framework GFForms::include_payment_addon_framework(); + GFForms::include_addon_framework(); // Require Braintree Payments core if(!class_exists('Braintree')) { @@ -76,8 +77,11 @@ public function init() } // Require plugin entry point + require_once $path . 'includes/angelleye-gravity-braintree-helper.php'; require_once $path . 'lib/class.plugify-gform-braintree.php'; - require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; + require_once $path . 'includes/class-angelleye-gravity-braintree-ach-field.php'; + require_once $path . 'includes/class-angelleye-gravity-braintree-ach-toggle-field.php'; + require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; require_once $path . 'includes/angelleye-gravity-braintree-field-mapping.php'; /** @@ -90,6 +94,12 @@ public function init() // Fire off entry point new Plugify_GForm_Braintree(); new AngelleyeGravityBraintreeFieldMapping(); + + /** + * Register the ACH form field and Payment Method toggle field + */ + GF_Fields::register( new Angelleye_Gravity_Braintree_ACH_Field() ); + GF_Fields::register( new Angelleye_Gravity_Braintree_ACH_Toggle_Field() ); AngellEYE_GForm_Braintree_Payment_Logger::instance(); } diff --git a/assets/js/angelleye-braintree-ach-cc.js b/assets/js/angelleye-braintree-ach-cc.js new file mode 100644 index 0000000..f5b95af --- /dev/null +++ b/assets/js/angelleye-braintree-ach-cc.js @@ -0,0 +1,192 @@ +jQuery(document).ready(function ($) { + if($('.gform_payment_method_options').length){ + var payment_methods = {}; + $('.gform_payment_method_options input[type=radio]').each(function () { + var targetdiv = $(this).attr('targetdiv'); + var value = $(this).val(); + payment_methods[value] = targetdiv; + }); + + $('.gform_payment_method_options').on('click','input[type=radio]', function () { + var selectedradio = $(this).val(); + for (var i in payment_methods) + if(i!==selectedradio) + $(this).closest('form').find('#'+payment_methods[i]).slideUp() + + var targetdiv = $(this).attr('targetdiv'); + $(this).closest('form').find('#'+targetdiv).slideDown(); + }); + + var selectedradio = $('.gform_payment_method_options input[type=radio]:checked').val(); + + switch(selectedradio){ + case 'braintree_ach': + $('.gform_payment_method_options input[value=braintree_ach]').trigger('click'); + break; + default: + case 'creditcard': + $('.gform_payment_method_options input[value=creditcard]').trigger('click'); + break; + } + } + + + + $('.custom_ach_form_submit_btn').click(function (e) { + e.preventDefault(); + + var curlabel = $(this).html(); + var form = $(this).closest('form'); + + var selectedradio = form.find('.gform_payment_method_options input[type=radio]:checked').val(); + + var check_if_ach_form = form.find('.ginput_ach_form_container'); + if(check_if_ach_form.length && (typeof selectedradio ==='undefined' || selectedradio === 'braintree_ach')){ + if(form.find('.ginput_container_address').length==0){ + alert('ACH payment requires billing address fields, so please include Billing Address field in your Gravity form.'); + return; + } + + var account_number = form.find('.ginput_account_number').val(); + var account_type = form.find('.ginput_account_type').val(); + var routing_number = form.find('.ginput_routing_number').val(); + var account_holdername = form.find('.ginput_account_holdername').val(); + + var streetAddress = form.find('.ginput_container_address .address_line_1 input[type=text]').val(); + var extendedAddress = form.find('.ginput_container_address .address_line_2 input[type=text]').val(); + var locality = form.find('.ginput_container_address .address_city input[type=text]').val(); + var region = form.find('.ginput_container_address .address_state input[type=text]').val(); + var postalCode = form.find('.ginput_container_address .address_zip input[type=text]').val(); + + if(streetAddress==''){ + alert('Please enter street address'); + return; + } + + if(locality==''){ + alert('Please enter your city'); + return; + } + + if(region==''){ + alert('Please enter your state'); + return; + } + + if(postalCode==''){ + alert('Please enter your Zip/Postal Code'); + return; + } + + if(account_number=='' || routing_number=='' || isNaN(account_number) || isNaN(routing_number)){ + alert('Please enter valid account number and routing number'); + return; + } + + if(account_type==''){ + alert('Please select account type.'); + return; + } + + if(account_holdername==''){ + alert('Please enter account holder name.'); + return; + } + + var account_holder_namebreak = account_holdername.split(' '); + if(account_type=='S' && account_holder_namebreak.length<2){ + alert('Please enter account holder first name and last name.'); + return; + } + + var submitbtn = $(this); + submitbtn.attr('disabled', true).html('Please wait...').css('opacity', '0.4'); + + braintree.client.create({ + authorization: angelleye_gravity_form_braintree_ach_handler_strings.ach_bt_token + }, function (clientErr, clientInstance) { + if (clientErr) { + alert('There was an error creating the Client, Please check your Braintree Settings.'); + console.error('clientErr',clientErr); + return; + } + + braintree.dataCollector.create({ + client: clientInstance, + paypal: true + }, function (err, dataCollectorInstance) { + if (err) { + alert('We are unable to validate your computer request, please try again.'); + resetButtonLoading(submitbtn, curlabel); + console.error('dataCollectorError',err); + return; + } + + var deviceData = dataCollectorInstance.deviceData; + + braintree.usBankAccount.create({ + client: clientInstance + }, function (usBankAccountErr, usBankAccountInstance) { + if (usBankAccountErr) { + alert('There was an error in initating bank request, Please try again.'); + resetButtonLoading(submitbtn, curlabel); + console.error('usBankAccountErr',usBankAccountErr); + return; + } + + var bankDetails = { + accountNumber: account_number, //'1000000000', + routingNumber: routing_number, //'011000015', + accountType: account_type == 'S' ? 'savings' : 'checking', + ownershipType: account_type == 'S' ? 'personal' : 'business', + billingAddress: { + streetAddress: streetAddress, //'1111 Thistle Ave', + extendedAddress: extendedAddress, + locality: locality, //'Fountain Valley', + region: region, //'CA', + postalCode: postalCode //'92708' + } + }; + + if (bankDetails.ownershipType === 'personal') { + bankDetails.firstName = account_holder_namebreak[0]; + bankDetails.lastName = account_holder_namebreak[1]; + } else { + bankDetails.businessName = account_holdername; + } + + usBankAccountInstance.tokenize({ + bankDetails: bankDetails, + mandateText: 'By clicking ["Submit"], I authorize Braintree, a service of PayPal, on behalf of ' + angelleye_gravity_form_braintree_ach_handler_strings.ach_business_name + ' (i) to verify my bank account information using bank information and consumer reports and (ii) to debit my bank account.' + }, function (tokenizeErr, tokenizedPayload) { + if (tokenizeErr) { + var errormsg = tokenizeErr['details']['originalError']['details']['originalError'][0]['message']; + if (errormsg.indexOf("Variable 'zipCode' has an invalid value") != -1) + alert('Please enter valid zip code.'); + else if (errormsg.indexOf("Variable 'state' has an invalid value") != -1) + alert('Please enter valid 2 Char State/Region code.'); + else + alert(errormsg); + + resetButtonLoading(submitbtn, curlabel); + console.error('tokenizeErr', tokenizeErr); + return; + } + + form.append(""); + form.append(''); + form.submit(); + }); + }); + }); + }); + + }else { + form.submit(); + } + }); +}); + +function resetButtonLoading(submitbtn, curlabel) { + submitbtn.attr('disabled', false).html(curlabel).css('opacity', '1'); +} diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index ae4d344..6ba2570 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -42,7 +42,7 @@ public function isCreditCardFieldExist($id) $get_form = GFAPI::get_form($id); if(isset($get_form['fields'])) { foreach ($get_form['fields'] as $single_field) { - if ($single_field->type == 'creditcard') { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach') { return true; } } diff --git a/includes/angelleye-gravity-braintree-helper.php b/includes/angelleye-gravity-braintree-helper.php new file mode 100644 index 0000000..4b02794 --- /dev/null +++ b/includes/angelleye-gravity-braintree-helper.php @@ -0,0 +1,49 @@ + false, + 'braintree_ach' => false, + 'braintree_ach_cc_toggle' => false + ]; + + if(isset($form['fields'])) { + foreach ($form['fields'] as $single_field) { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type == 'braintree_ach_cc_toggle') { + $response[$single_field->type] = $single_field; + } + } + } + + return $response; +} + +/** + * This is to setup default values for Custom Toggle and ACH form fields in admin panel + */ + +add_action( 'gform_loaded', function (){ + add_action( 'gform_editor_js_set_default_values', 'gravityFormSetDefaultValueOnDropin' ); + function gravityFormSetDefaultValueOnDropin() { + ?> + case "braintree_ach" : + if (!field.label) + field.label = ; + var accNumber, accType, routingNumber, accName; + + accNumber = new Input(field.id + ".1", ); + accType = new Input(field.id + ".2", ); + routingNumber = new Input(field.id + ".3", ); + accName = new Input(field.id + ".4", ); + field.inputs = [accNumber, accType, routingNumber, accName]; + break; + case "braintree_ach_cc_toggle": + if (!field.label) + field.label = ; + var paymentMethodToggle; + paymentMethodToggle = new Input(field.id + ".1", ); + field.inputs = [paymentMethodToggle]; + break; + 'pricing_fields', 'text' => 'ACH Form' ]; + } + + /** + * The settings which should be available on the field in the form editor. + * + * @return array + */ + function get_form_editor_field_settings() { + return ['label_setting', 'label_placement_setting', 'admin_label_setting', 'description_setting', 'sub_labels_setting', + 'sub_label_placement_setting', 'error_message_setting', 'css_class_setting', 'conditional_logic_field_setting', + 'force_ssl_field_setting', 'rules_setting', 'input_placeholders_setting', + ]; + } + + /** + * Enable this field for use with conditional logic. + * + * @return bool + */ + public function is_conditional_logic_supported() { + return true; + } + + /** + * The scripts to be included in the form editor. + * + * @return string + */ + public function get_form_editor_inline_script_on_page_render() { + + } + + /** + * Override default button for the ACH Payments + * @param $button + * @param $form + * + * @return string + */ + function overrideSubmitButton( $button, $form ) { + return ""; + } + + /** + * Returns the fields input for backend and frontend + * @param array $form + * @param string $value + * @param null $entry + * + * @return string + */ + public function get_field_input( $form, $value = '', $entry = null ) { + add_filter( 'gform_submit_button', [$this, 'overrideSubmitButton'], 10, 2 ); + $is_entry_detail = $this->is_entry_detail(); + $is_form_editor = $this->is_form_editor(); + + $form_id = $form['id']; + $id = intval( $this->id ); + $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; + $form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id; + + $disabled_text = $is_form_editor ? "disabled='disabled'" : ''; + $class_suffix = $is_entry_detail ? '_admin' : ''; + + $sub_label_placement = rgar( $form, 'subLabelPlacement' ); + $field_sub_label_placement = $this->subLabelPlacement; + $is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $sub_label_placement == 'above' ); + $sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : ''; + + $account_number = ''; + $routing_number = ''; + $account_type = ''; + $autocomplete = RGFormsModel::is_html5_enabled() ? "autocomplete='off'" : ''; + + if ( is_array( $value ) ) { + $account_number = esc_attr( rgget( $this->id . '.1', $value ) ); + $account_type = esc_attr( rgget( $this->id . '.2', $value ) ); + $routing_number = esc_attr( rgget( $this->id . '.3', $value ) ); + $account_holder_name= esc_attr( rgget( $this->id . '.4', $value ) ); + } + + + $tabindex = $this->get_tabindex(); + $account_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' ); + $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; + $account_number_label = rgar( $account_number_field_input, 'customLabel' ) != '' ? $account_number_field_input['customLabel'] : __( 'Account Number', 'gravity-forms-braintree' ); + $account_number_label = gf_apply_filters( array( 'gform_1', $form_id ), $account_number_label, $form_id ); + + $account_number_placeholder = $this->get_input_placeholder_attribute( $account_number_field_input ); + if ( $is_sub_label_above ) { + $account_field = " + + + "; + } else { + $account_field = " + + + "; + } + + $tabindex = $this->get_tabindex(); + $account_type_field_input = GFFormsModel::get_input( $this, $this->id . '.2' ); + $account_type_options = $this->getAccountTypeSelectOptions( $account_type ); + $account_type_label = rgar( $account_type_field_input, 'customLabel' ) != '' ? $account_type_field_input['customLabel'] : __( 'Account Type', 'gravity-forms-braintree' ); + $account_type_label = gf_apply_filters( array( 'gform_accounttype', $form_id ), $account_type_label, $form_id ); + if ( $is_sub_label_above ) { + $account_type_field = " + + + "; + } else { + $account_type_field = " + + + "; + } + + $tabindex = $this->get_tabindex(); + $routing_number_field_input = GFFormsModel::get_input( $this, $this->id . '.3' ); + $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; + $routing_number_label = rgar( $routing_number_field_input, 'customLabel' ) != '' ? $routing_number_field_input['customLabel'] : __( 'Routing Number', 'gravity-forms-braintree' ); + $routing_number_label = gf_apply_filters( array( 'gform_routingnumber', $form_id ), $routing_number_label, $form_id ); + + $routing_number_placeholder = $this->get_input_placeholder_attribute( $routing_number_field_input ); + if ( $is_sub_label_above ) { + $routing_field = " + + + "; + } else { + $routing_field = " + + + "; + } + + $tabindex = $this->get_tabindex(); + $account_holder_name_field_input = GFFormsModel::get_input( $this, $this->id . '.4' ); + $account_holder_name_label = rgar( $account_holder_name_field_input, 'customLabel' ) != '' ? $account_holder_name_field_input['customLabel'] : __( 'Account Holder Name', 'gravity-forms-braintree' ); + $account_holder_name_label = gf_apply_filters( array( 'gform_accountholdername', $form_id ), $account_holder_name_label, $form_id ); + + $account_holder_name_placeholder = $this->get_input_placeholder_attribute( $account_holder_name_field_input ); + if ( $is_sub_label_above ) { + $account_holder_name_field = " + + + "; + } else { + $account_holder_name_field = " + + + "; + } + + return "
" . $account_field . $account_type_field . $routing_field . $account_holder_name_field . '
'; + + } + + /** + * Returns Braintree ACH Supported account types + * @return mixed|void + */ + public function getAccountTypeList() { + $account_types = apply_filters( 'angelleye_gravity_braintree_account_types', [ + 'S' => __( 'Savings', 'gravity-forms-braintree' ), + 'C' => __( 'Checking', 'gravity-forms-braintree' ), + ]); + return $account_types; + } + + /** + * Returns the account type options for select field + * @param $selected_value + * @param string $placeholder + * + * @return string + */ + private function getAccountTypeSelectOptions( $selected_value, $placeholder = '' ) { + if ( empty( $placeholder ) ) { + $placeholder = __( 'Select', 'gravity-forms-braintree' ); + } + $options = $this->getAccountTypeList(); + $str = ""; + foreach ( $options as $value => $label ) { + $selected = $selected_value == $value ? "selected='selected'" : ''; + $str .= ""; + } + + return $str; + } + + public function get_field_label_class(){ + return 'gfield_label gfield_label_before_complex'; + } + + public function is_value_submission_empty( $form_id ) { + return false; + } + + /** + * When customer chooses ACH form method then avoid credit card field validation errors + * @param $validation_result + * + * @return mixed + */ + function customCCValidation($validation_result){ + $form = $validation_result['form']; + $failed_validation = 0; + if(isset($form['fields'])) { + + foreach ($form['fields'] as $key => $single_field) { + if ($single_field->type == 'creditcard') { + $form['fields'][$key]['failed_validation'] = false; + $form['fields'][$key]['validation_message'] = ''; + }else if($single_field['failed_validation']) + $failed_validation++; + } + } + + $validation_result['form']=$form; + if($failed_validation == 0){ + $validation_result['failed_validation_page'] = "1"; + $validation_result['is_valid'] = true; + } + + return $validation_result; + } + + /** + * Constructor to add custom validation filter to exclude CC validation when ACH payment method is selected + * Angelleye_Gravity_Braintree_ACH_Field constructor. + * + * @param array $data + */ + public function __construct( $data = array() ) { + parent::__construct($data); + add_filter( 'gform_validation', [$this, 'customCCValidation'], 10 ); + } + + /** + * Validate the user input + * @param array|string $value + * @param array $form + */ + public function validate( $value, $form ) { + + //check if toggle field exist + $selected_payment_method = 'braintree_ach'; + $response = getAngelleyeBraintreePaymentFields($form); + if($response['braintree_ach_cc_toggle']!==false){ + $selected_payment_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); + } + + if($selected_payment_method!=='braintree_ach') { + return; + } + + $account_number = rgpost( 'input_' . $this->id . '_1' ); + $routing_number = rgpost( 'input_' . $this->id . '_2' ); + $account_type = rgpost( 'input_' . $this->id . '_3' ); + $account_holder_name= rgpost( 'input_' . $this->id . '_4' ); + + //$this->isRequired && + if ( ( empty( $account_number ) || empty( $routing_number ) || empty( $account_type ) || empty($account_holder_name) ) ) { + $this->failed_validation = true; + $this->validation_message = empty( $this->errorMessage ) ? __( 'Please enter your bank account information.', 'gravity-forms-braintree' ) : $this->errorMessage; + } elseif ( !empty( $account_number ) ) { + + if ( empty( $routing_number ) ) { + $this->failed_validation = true; + $this->validation_message = __( "Please enter your bank account's routing number.", 'gravity-forms-braintree' ); + } + if ( empty( $account_type ) ) { + $this->failed_validation = true; + $this->validation_message = __( "Please select the account type.", 'gravity-forms-braintree' ); + } + + if ( empty( $account_holder_name ) ) { + $this->failed_validation = true; + $this->validation_message = __( "Please enter account holder name.", 'gravity-forms-braintree' ); + } + } + } + + /** + * Shows the filled information by the users on frontend form + * @param array $field_values + * @param bool $get_from_post_global_var + * + * @return array|string + */ + public function get_value_submission( $field_values, $get_from_post_global_var = true ) { + + if ( $get_from_post_global_var ) { + $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( $this->inputs[0], 'name' ), $field_values, true ); + $value[ $this->id . '.2' ] = $this->get_input_value_submission( 'input_' . $this->id . '_2', rgar( $this->inputs[1], 'name' ), $field_values, true ); + $value[ $this->id . '.3' ] = $this->get_input_value_submission( 'input_' . $this->id . '_3', rgar( $this->inputs[2], 'name' ), $field_values, true ); + $value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', rgar( $this->inputs[3], 'name' ), $field_values, true ); + } else { + $value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var ); + } + return $value; + } + + /** + * Returns the ACH form entry input values + * @return array|null + */ + public function get_entry_inputs() { + $inputs = array(); + // only store account type and number input values + foreach ( $this->inputs as $input ) { + if ( in_array( $input['id'], array( $this->id . '.1', $this->id . '.2', $this->id . '.3', $this->id . '.4' ) ) ) { + $inputs[] = $input; + } + } + + return $inputs; + } + + + public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) { + + $allowable_tags = $this->get_allowable_tags( $form['id'] ); + + if ( $allowable_tags === false ) { + // The value is unsafe so encode the value. + $return = esc_html( $value ); + } else { + // The value contains HTML but the value was sanitized before saving. + $return = $value; + } + + return $return; + } + + /** + * Returns the ACH form value on Entry detail page + * @param array|string $value + * @param string $currency + * @param bool $use_text + * @param string $format + * @param string $media + * + * @return string + */ + public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) { + + if ( is_array( $value ) ) { + $account_number = trim( rgget( $this->id . '.1', $value ) ); + $account_type = trim( rgget( $this->id . '.2', $value ) ); + $routing_number = trim( rgget( $this->id . '.3', $value ) ); + $account_holder_name = trim( rgget( $this->id . '.4', $value ) ); + if($format=='html') + return "Account Number: $account_number
+Account Type: ".($account_type=='s'?'Savings':'Checking')."
+Routing Number: $routing_number
+Account Holder: $account_holder_name
"; + } else { + return ''; + } + } + + /** + * Mask the values before saving + * @param string $value + * @param array $form + * @param string $input_name + * @param int $lead_id + * @param array $lead + * + * @return array|string + */ + public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) { + list( $input_token, $field_id_token, $input_id ) = rgexplode( '_', $input_name, 3 ); + /*if ( $input_id == '1' ) { + $value = str_replace( ' ', '', $value ); + $card_number_length = strlen( $value ); + $value = substr( $value, - 4, 4 ); + $value = str_pad( $value, $card_number_length, 'X', STR_PAD_LEFT ); + } elseif ( $input_id == '3' ) { + $value = rgpost( "input_{$field_id_token}_3" ); + }*/ + + return $this->sanitize_entry_value( $value, $form['id'] ); + } +} diff --git a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php new file mode 100644 index 0000000..0f804a3 --- /dev/null +++ b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php @@ -0,0 +1,136 @@ + 'pricing_fields', 'text' => 'Method Toggle' ]; + } + + /** + * The settings which should be available on the field in the form editor. + * + * @return array + */ + function get_form_editor_field_settings() { + return ['label_setting', 'admin_label_setting', 'description_setting', 'error_message_setting', 'css_class_setting', 'conditional_logic_field_setting', + 'rules_setting', 'input_placeholders_setting', + ]; + } + + /** + * Return the Payment method toggle radio buttons + * @param array $form + * @param string $value + * @param null $entry + * + * @return string + */ + public function get_field_input( $form, $value = '', $entry = null ) { + + $is_entry_detail = $this->is_entry_detail(); + $is_form_editor = $this->is_form_editor(); + + $form_id = $form['id']; + $id = intval( $this->id ); + $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; + $form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id; + + $cc_field_id = ''; + $ach_field_id = ''; + if(!$is_form_editor && !$is_entry_detail){ + foreach ($form['fields'] as $single_field) { + + if ($single_field->type == 'creditcard') + $cc_field_id = $single_field->id; + else if($single_field->type=='braintree_ach') { + $ach_field_id = $single_field->id; + } + } + } + + $payment_options = ''; + $payment_methods = [['key' => 'creditcard', 'label'=>'Credit Card', 'field_id' => $cc_field_id], + ['key' => 'braintree_ach', 'label' => 'ACH', 'field_id' => $ach_field_id]]; + foreach ( $payment_methods as $payment_method ) { + $checked = rgpost( "input_{$id}_1" ) == $payment_method['key'] ? "checked='checked'" : ''; + $payment_options .= "
{$payment_method['label']}
"; + } + + return "
" .$payment_options + . '
'; + } + + public function is_value_submission_empty( $form_id ) { + return false; + } + + public function get_entry_inputs() { + $inputs = array(); + foreach ( $this->inputs as $input ) { + if ( in_array( $input['id'], array( $this->id . '.1') ) ) { + $inputs[] = $input; + } + } + + return $inputs; + } + + /** + * Validate the user input + * @param array|string $value + * @param array $form + */ + public function validate( $value, $form ) { + $toggle_selected = rgpost( 'input_' . $this->id.'_1' ); + + if (empty( $toggle_selected ) || !in_array($toggle_selected, ['creditcard','braintree_ach']) ) { + $this->failed_validation = true; + $this->validation_message = empty( $this->errorMessage ) ? __( 'Please select a payment method.', 'gravity-forms-braintree' ) : $this->errorMessage; + } + } + + /** + * Shows the filled information by the users + * @param array $field_values + * @param bool $get_from_post_global_var + * + * @return array|string + */ + public function get_value_submission( $field_values, $get_from_post_global_var = true ) { + + if ( $get_from_post_global_var ) { + $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( $this->inputs[0], 'name' ), $field_values, true ); + } else { + $value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var ); + } + return $value; + } + + public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) { + + if ( is_array( $value ) ) { + $selected_method = trim( rgget( $this->id . '.1', $value ) ); + return$selected_method=='braintree_ach' ? 'Braintree ACH Direct Debit' : 'Credit Card'; + } else { + return ''; + } + } +} \ No newline at end of file diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 7bb42ee..f838539 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -16,6 +16,8 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { protected $_supports_callbacks = false; protected $_enable_rg_autoupgrade = true; + protected $selected_payment_method = 'creditcard'; + /** * Class constructor. Send __construct call to parent * @since 1.0 @@ -34,6 +36,34 @@ public function __construct () { parent::__construct(); } + /** + * Override credit card field check, so that we can return true when someone has ach form + * If any user will have any form then same payment gateway class will be used + * @param array $form + * + * @return bool + */ + public function has_credit_card_field( $form ) { + if(isset($form['fields'])) { + foreach ($form['fields'] as $single_field) { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach') { + return true; + } + } + } + return $this->get_credit_card_field( $form ) !== false; + } + + /** + * Override default message for Gravity Form Braintree Feeds + * @return string + */ + public function requires_credit_card_message() { + $url = add_query_arg( array( 'view' => null, 'subview' => null ) ); + + return sprintf( esc_html__( "You must add a Credit Card/ACH Payment field to your form before creating a feed. Let's go %sadd one%s!", 'gravityforms' ), "", '' ); + } + /** * Override init_frontend to assign front end based filters and actions required for operation * @@ -47,6 +77,190 @@ public function init_frontend () { } + /** + * Init the Braintree configuration and return gateway for transactions, etc. + * @return bool|\Braintree\Gateway + * @throws \Braintree\Exception\Configuration + */ + public function getBraintreeGateway() { + $settings = $this->get_plugin_settings(); + if(!$settings) + return false; + + // Configure Braintree environment + $braintree_config = new \Braintree\Configuration([ + 'environment' => strtolower( $settings['environment'] ) , + 'merchantId' => $settings['merchant-id'], + 'publicKey' => $settings['public-key'], + 'privateKey' => $settings['private-key'] + ]); + + $braintree_config->timeout(60); + + $gateway = new Braintree\Gateway($braintree_config); + return $gateway; + } + + /** + * ACH Payment authorization + * @param $feed + * @param $submission_data + * @param $form + * @param $entry + * + * @return array|bool + * @throws \Braintree\Exception\Configuration + */ + public function ach_authorize( $feed, $submission_data, $form, $entry ) { + $this->log_debug( "Braintree_ACH_Authorize::START" ); + // Prepare authorization response payload + $authorization = array( + 'is_authorized' => false, + 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'We are unable to authorize the bank account, Please try again.', 'gravity-forms-braintree' ) ), + 'transaction_id' => '', + 'captured_payment' => array( + 'is_success' => false, + 'error_message' => '', + 'transaction_id' => '', + 'amount' => $submission_data['payment_amount'] + ) + ); + + $ach_device_corelation = rgpost('ach_device_corelation'); + $ach_token = rgpost('ach_token'); + $payment_amount = number_format($submission_data['payment_amount'],2,'.',''); + + $gateway = $this->getBraintreeGateway(); + if( $gateway !== false ) { + $settings = $this->get_plugin_settings(); + $response = getAngelleyeBraintreePaymentFields($form); + $braintree_ach_field = $response['braintree_ach']; + $account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); + $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); + $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' ); + $account_holder_name = rgpost( 'input_' . $braintree_ach_field->id . '_4' ); + + $account_holder_name = explode(' ', $account_holder_name); + /** + * Create customer in Braintree + */ + $customer_request = [ + 'firstName' => @$account_holder_name[0], + 'lastName' => end($account_holder_name), + ]; + $this->log_debug( "Braintree_ACH_Customer::create REQUEST => " . print_r( $customer_request, 1 ) ); + $customer_result = $gateway->customer()->create( $customer_request ); + $this->log_debug( "Braintree_ACH_Customer::create RESPONSE => " . print_r( $customer_result, 1 ) ); + + if ( $customer_result->success ) { + $payment_method_request = [ + 'customerId' => $customer_result->customer->id, + 'paymentMethodNonce' => $ach_token, + 'options' => [ + 'usBankAccountVerificationMethod' => Braintree\Result\UsBankAccountVerification::NETWORK_CHECK + ] + ]; + + $this->log_debug( "Braintree_ACH_PaymentRequest::create REQUEST => " . print_r( $payment_method_request, 1 ) ); + $payment_method_response = $gateway->paymentMethod()->create( $payment_method_request ); + $this->log_debug( "Braintree_ACH_PaymentRequest::create RESPONSE => " . print_r( $payment_method_response, 1 ) ); + + if(isset($payment_method_response->paymentMethod->token)) { + + $sale_request = [ + 'amount' => $payment_amount, + 'paymentMethodToken' => $payment_method_response->paymentMethod->token, + 'deviceData' => $ach_device_corelation, + 'options' => [ + 'submitForSettlement' => true + ] + ]; + + $this->log_debug( "Braintree_ACH_Transaction::sale REQUEST => " . print_r( $sale_request, 1 ) ); + $sale_response = $gateway->transaction()->sale($sale_request); + $this->log_debug( "Braintree_ACH_Transaction::sale RESPONSE => " . print_r( $sale_response, 1 ) ); + + if ( $sale_response->success ) { + do_action('angelleye_gravity_forms_response_data', $sale_response, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree_ach'); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $sale_response->transaction->id; + + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $sale_response->transaction->id, + 'amount' => $sale_response->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Braintree ACH' + ); + + $this->log_debug( "Braintree_ACH::SUCCESS"); + } else { + if( isset( $sale_response->transaction->processorResponseText ) ) { + $authorization['error_message'] = sprintf( 'Your bank did not authorized the transaction: %s.', $sale_response->transaction->processorResponseText); + }else { + $authorization['error_message'] = sprintf( 'Your bank declined the transaction, please try again or contact bank.'); + } + $this->log_debug( "Braintree_ACH::FAILED_ERROR"); + } + } else { + $authorization['error_message'] = __('We are unable to authorize bank account, This may have happened due to expired token, please try again.', 'gravity-forms-braintree'); + } + } else { + $authorization['error_message'] = __('Unable to proceed with the transaction due to invalid name.', 'gravity-forms-braintree'); + } + + return $authorization; + } + + $this->log_debug( "Braintree_ACH::FAILED"); + return false; + + } + + /** + * Gets the payment validation result. + * + * @since Unknown + * @access public + * + * @used-by GFPaymentAddOn::validation() + * + * @param array $validation_result Contains the form validation results. + * @param array $authorization_result Contains the form authorization results. + * + * @return array The validation result for the credit card field. + */ + public function get_validation_result( $validation_result, $authorization_result ) { + + $credit_card_page = 0; + if($this->selected_payment_method=='braintree_ach'){ + foreach ( $validation_result['form']['fields'] as &$field ) { + if ( $field->type == 'braintree_ach' ) { + $field->failed_validation = true; + $field->validation_message = $authorization_result['error_message']; + $credit_card_page = $field->pageNumber; + break; + } + } + }else { + foreach ( $validation_result['form']['fields'] as &$field ) { + if ( $field->type == 'creditcard' ) { + $field->failed_validation = true; + $field->validation_message = $authorization_result['error_message']; + $credit_card_page = $field->pageNumber; + break; + } + } + } + $validation_result['credit_card_page'] = $credit_card_page; + $validation_result['is_valid'] = false; + + return $validation_result; + + } + + /** * After form has been submitted, send CC details to Braintree and ensure the card is going to work * If not, void the validation result (processed elsewhere) and have the submit the form again @@ -69,6 +283,22 @@ public function init_frontend () { */ public function authorize( $feed, $submission_data, $form, $entry ) { + $selected_payment_method = 'braintree_ach'; + $response = getAngelleyeBraintreePaymentFields($form); + if($response['braintree_ach_cc_toggle']!==false){ + $selected_payment_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); + }else { + //This means there was no toggle button, Need to identify based on the fields + if($response['creditcard']!==false) + $selected_payment_method = 'creditcard'; + } + + $this->selected_payment_method = $selected_payment_method; + if($selected_payment_method=='braintree_ach'){ + return $this->ach_authorize($feed, $submission_data, $form, $entry); + } + + // Prepare authorization response payload $authorization = array( 'is_authorized' => false, @@ -104,17 +334,7 @@ public function authorize( $feed, $submission_data, $form, $entry ) { try { - // Configure Braintree environment - $braintree_config = new \Braintree\Configuration([ - 'environment' => strtolower( $settings['environment'] ) , - 'merchantId' => $settings['merchant-id'], - 'publicKey' => $settings['public-key'], - 'privateKey' => $settings['private-key'] - ]); - - $braintree_config->timeout(60); - - $gateway = new Braintree\Gateway($braintree_config); + $gateway = $this->getBraintreeGateway(); // Set to auto settlemt if applicable if( $settings['settlement'] == 'Yes' ) { @@ -233,6 +453,25 @@ public function plugin_settings_fields () { ) ) ), + array( + 'title' => 'Braintree ACH Settings', + 'fields' => array( + array( + 'name' => 'tokenization-key', + 'tooltip' => 'Your Braintree Tokenization Key', + 'label' => 'Tokenization Key', + 'type' => 'text', + 'class' => 'medium' + ), + array( + 'name' => 'business-name', + 'tooltip' => 'For all ACH transactions, you are required to collect a mandate or “proof of authorization” from the customer to prove that you have their explicit permission to debit their bank account. We will put your business name in authorization text', + 'label' => 'Business name', + 'type' => 'text', + 'class' => 'medium' + ) + ) + ), array( 'title' => 'Payment Settings', 'fields' => array( @@ -415,4 +654,71 @@ public function enqueue_styles_css() { } } + /** + * Load the Braintree JS and Custom JS in frontend + * @return array + */ + public function scripts() { + $translation_array = []; + $settings = $this->get_plugin_settings(); + if($settings!==false){ + $translation_array['ach_bt_token'] = $settings['tokenization-key']; + $translation_array['ach_business_name'] = $settings['business-name']; + } + + $scripts = array( + array( + 'handle' => 'angelleye-gravity-form-braintree-client', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/client.min.js', + 'version' => $this->_version, + 'deps' => array( 'jquery' ), + 'in_footer' => false, + 'callback' => array( $this, 'localize_scripts' ), + 'enqueue' => array( + array( 'field_types' => array( 'braintree_ach' ) ) + ) + ), + array( + 'handle' => 'angelleye-gravity-form-braintree-data-collector', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/data-collector.min.js', + 'version' => $this->_version, + 'deps' => array( ), + 'in_footer' => false, + 'callback' => array( $this, 'localize_scripts' ), + 'enqueue' => array( + array( 'field_types' => array( 'braintree_ach' ) ) + ) + ), + array( + 'handle' => 'angelleye-gravity-form-braintree-usbankaccount', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/us-bank-account.min.js', + 'version' => $this->_version, + 'deps' => array( ), + 'in_footer' => false, + 'callback' => array( $this, 'localize_scripts' ), + 'enqueue' => array( + array( 'field_types' => array( 'braintree_ach' ) ) + ) + ), + array( + 'handle' => 'angelleye_gravity_form_braintree_ach_handler', + 'src' => GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/angelleye-braintree-ach-cc.js', + 'version' => $this->_version, + 'deps' => array( 'jquery', 'angelleye-gravity-form-braintree-client', 'angelleye-gravity-form-braintree-data-collector', + 'angelleye-gravity-form-braintree-usbankaccount'), + 'in_footer' => false, + 'callback' => array( $this, 'localize_scripts' ), + 'strings' => $translation_array, + 'enqueue' => array( +// array( +// 'admin_page' => array( 'form_settings' ), +// 'tab' => 'simpleaddon' +// ) + array( 'field_types' => array( 'braintree_ach' ) ) + ) + ), + ); + + return array_merge( parent::scripts(), $scripts ); + } } \ No newline at end of file From 13968ab024a5f447a3c625342b47fbb8527b8abb Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 12 May 2020 02:17:48 +0530 Subject: [PATCH 69/99] Required plugin file added for Plugin requirement checker, GFB-22 --- includes/angelleye-plugin-requirement-checker.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/angelleye-plugin-requirement-checker.php b/includes/angelleye-plugin-requirement-checker.php index 286edb4..6c64e5b 100644 --- a/includes/angelleye-plugin-requirement-checker.php +++ b/includes/angelleye-plugin-requirement-checker.php @@ -72,6 +72,7 @@ public function check( $force_check = false ) { } if(count($this->required_plugins)){ + require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); $all_plugins = get_plugins(); $active_plugins = get_option('active_plugins'); foreach ($this->required_plugins as $single_plugin => $min_version_required){ From 55b6231fe5693e8b2a3b50b1364ccffd12d86057 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Wed, 13 May 2020 03:03:26 +0530 Subject: [PATCH 70/99] Entries list page and some PHP notice issues resolved , GFB-17 --- ...-angelleye-gravity-braintree-ach-field.php | 52 +++++++++++++++---- ...eye-gravity-braintree-ach-toggle-field.php | 10 ++-- lib/class.plugify-gform-braintree.php | 4 +- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index 24566b9..b9d9d38 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -100,6 +100,7 @@ public function get_field_input( $form, $value = '', $entry = null ) { $account_number = ''; $routing_number = ''; $account_type = ''; + $account_holder_name = ''; $autocomplete = RGFormsModel::is_html5_enabled() ? "autocomplete='off'" : ''; if ( is_array( $value ) ) { @@ -343,27 +344,55 @@ public function get_value_submission( $field_values, $get_from_post_global_var = */ public function get_entry_inputs() { $inputs = array(); - // only store account type and number input values - foreach ( $this->inputs as $input ) { - if ( in_array( $input['id'], array( $this->id . '.1', $this->id . '.2', $this->id . '.3', $this->id . '.4' ) ) ) { - $inputs[] = $input; + if(is_array($this->inputs)) { + foreach ( $this->inputs as $input ) { + if ( in_array( $input['id'], array( + $this->id . '.1', + $this->id . '.2', + $this->id . '.3', + $this->id . '.4' + ) ) ) { + $inputs[] = $input; + } } } return $inputs; } - + /** + * Format the entry value for display on the entries list page. + * + * Return a value that's safe to display on the page. + * + * @param string|array $value The field value. + * @param array $entry The Entry Object currently being processed. + * @param string $field_id The field or input ID currently being processed. + * @param array $columns The properties for the columns being displayed on the entry list page. + * @param array $form The Form Object currently being processed. + * + * @return string + */ public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) { $allowable_tags = $this->get_allowable_tags( $form['id'] ); - if ( $allowable_tags === false ) { - // The value is unsafe so encode the value. - $return = esc_html( $value ); - } else { - // The value contains HTML but the value was sanitized before saving. - $return = $value; + list( $input_id, $field_id ) = rgexplode( '.', $field_id, 2 ); + switch($field_id){ + case 2: + $return = $value=='C'?'Checking':'Savings'; + break; + case 1: + case 3: + case 4: + default: + if ( $allowable_tags === false ) { + // The value is unsafe so encode the value. + $return = esc_html( $value ); + } else { + // The value contains HTML but the value was sanitized before saving. + $return = $value; + } } return $return; @@ -419,4 +448,5 @@ public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lea return $this->sanitize_entry_value( $value, $form['id'] ); } + } diff --git a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php index 0f804a3..a0c6b0f 100644 --- a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php @@ -84,9 +84,11 @@ public function is_value_submission_empty( $form_id ) { public function get_entry_inputs() { $inputs = array(); - foreach ( $this->inputs as $input ) { - if ( in_array( $input['id'], array( $this->id . '.1') ) ) { - $inputs[] = $input; + if(is_array($this->inputs)) { + foreach ( $this->inputs as $input ) { + if ( in_array( $input['id'], array( $this->id . '.1' ) ) ) { + $inputs[] = $input; + } } } @@ -117,7 +119,7 @@ public function validate( $value, $form ) { public function get_value_submission( $field_values, $get_from_post_global_var = true ) { if ( $get_from_post_global_var ) { - $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( $this->inputs[0], 'name' ), $field_values, true ); + $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( @$this->inputs[0], 'name' ), $field_values, true ); } else { $value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var ); } diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index f838539..7d7687d 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -662,8 +662,8 @@ public function scripts() { $translation_array = []; $settings = $this->get_plugin_settings(); if($settings!==false){ - $translation_array['ach_bt_token'] = $settings['tokenization-key']; - $translation_array['ach_business_name'] = $settings['business-name']; + $translation_array['ach_bt_token'] = @$settings['tokenization-key']; + $translation_array['ach_business_name'] = @$settings['business-name']; } $scripts = array( From b779871fdab1675a4c1ab62467da1fa9ee09a89f Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Wed, 13 May 2020 03:17:18 +0530 Subject: [PATCH 71/99] Updated the missing plugin install link or reactivate the plugin quickly, removed the caching logic, GFB-22 --- angelleye-gravity-forms-braintree.php | 4 +- .../angelleye-plugin-requirement-checker.php | 40 +++++++++++++------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index e857645..6922444 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -64,8 +64,8 @@ public function requirementCheck() { $checker->setPHP('7.2'); $checker->setRequiredClasses(['GFForms' => 'Gravity forms plugin is required to run the Gravity Forms Braintree.']); $checker->setRequiredExtensions(['xmlwriter', 'openssl', 'dom', 'hash', 'curl']); - $checker->setRequiredPlugins(['gravityforms/gravityforms.php'=>'2.4']); - $checker->setDeactivatePlugins([self::$plugin_base_file]); + $checker->setRequiredPlugins(['gravityforms/gravityforms.php'=>['ver'=>'2.4', 'install_link'=>'https://www.gravityforms.com/pricing/']]); + //$checker->setDeactivatePlugins([self::$plugin_base_file]); if($checker->check()===true) { $this->init(); } diff --git a/includes/angelleye-plugin-requirement-checker.php b/includes/angelleye-plugin-requirement-checker.php index 6c64e5b..2e51569 100644 --- a/includes/angelleye-plugin-requirement-checker.php +++ b/includes/angelleye-plugin-requirement-checker.php @@ -60,10 +60,6 @@ public function setRequiredExtensions( $extensions ) { } public function check( $force_check = false ) { - $check = get_option($this->plugin_check_option_name); - if($check=='passed' && !$force_check) - return true; - if(count($this->required_classes)){ foreach ($this->required_classes as $class_name => $class_msg){ if(!class_exists($class_name)) @@ -75,21 +71,23 @@ public function check( $force_check = false ) { require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); $all_plugins = get_plugins(); $active_plugins = get_option('active_plugins'); - foreach ($this->required_plugins as $single_plugin => $min_version_required){ + foreach ($this->required_plugins as $single_plugin => $plugin_options){ if(in_array($single_plugin, $active_plugins)){ - if(version_compare($all_plugins[$single_plugin]['Version'], $min_version_required, '<')){ - $this->errors_list[] = 'You have '.$all_plugins[$single_plugin]['Name'].' - Version: '.$all_plugins[$single_plugin]['Version'].' active, we require min '.$all_plugins[$single_plugin]['Name'].' - Version: '.$min_version_required.' to run the '.$this->plugin_name; + if(isset($plugin_options['ver'])) { + $min_version_required = $plugin_options['ver']; + if ( version_compare( $all_plugins[ $single_plugin ]['Version'], $min_version_required, '<' ) ) { + $this->errors_list[] = 'You have ' . $all_plugins[ $single_plugin ]['Name'] . ' - Version: ' . $all_plugins[ $single_plugin ]['Version'] . ' active, we require min ' . $all_plugins[ $single_plugin ]['Name'] . ' - Version: ' . $min_version_required . ' to run the ' . $this->plugin_name; + } } }else if(isset($all_plugins[$single_plugin])) { - $this->errors_list[] = 'Please activate '.$all_plugins[$single_plugin]['Name'].' plugin to run the '.$this->plugin_name; + $this->errors_list[] = 'Please activate '.$all_plugins[$single_plugin]['Name'].' plugin to run the '.$this->plugin_name; } else{ - $this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.'; + if(isset($plugin_options['install_link'])) + $this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.'; + else + $this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.'; } } - /*echo '
';
-				print_r($all_plugins);
-				print_r($active_plugins);die;*/
-
 			}
 
 			if(count($this->required_extensions)) {
@@ -142,5 +140,21 @@ public function checkPluginDeactivation( $new_value, $old_value ) {
 					deactivate_plugins($single_plugin_basename, true);
 			}
 		}
+
+		/**
+		 * Get activation or deactivation link of a plugin
+		 * @param string $plugin plugin file name
+		 * @param string $action action to perform. activate or deactivate
+		 * @return string $url action url
+		 */
+		function pluginActionLink( $plugin, $action = 'activate' ) {
+			if ( strpos( $plugin, '/' ) ) {
+				$plugin = str_replace( '\/', '%2F', $plugin );
+			}
+			$url = sprintf( admin_url( 'plugins.php?action=' . $action . '&plugin=%s&plugin_status=all&paged=1&s' ), $plugin );
+			$_REQUEST['plugin'] = $plugin;
+			$url = wp_nonce_url( $url, $action . '-plugin_' . $plugin );
+			return $url;
+		}
 	}
 }
\ No newline at end of file

From 03a4de40d7039ab8b495bc73e361477e001630a4 Mon Sep 17 00:00:00 2001
From: Deepak Maurya 
Date: Wed, 13 May 2020 22:53:16 +0530
Subject: [PATCH 72/99] Updated the requirement verbiages, GFB-22

---
 angelleye-gravity-forms-braintree.php         |  4 +--
 .../angelleye-plugin-requirement-checker.php  | 35 ++++++++++++-------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php
index 6922444..44d42e1 100644
--- a/angelleye-gravity-forms-braintree.php
+++ b/angelleye-gravity-forms-braintree.php
@@ -62,9 +62,9 @@ public function __construct()
 	public function requirementCheck() {
 		$checker = new Angelleye_Plugin_Requirement_Checker('Gravity Forms Braintree Payments', self::$version, self::$plugin_base_file);
 		$checker->setPHP('7.2');
-		$checker->setRequiredClasses(['GFForms' => 'Gravity forms plugin is required to run the Gravity Forms Braintree.']);
+		$checker->setRequiredClasses(['GFForms' => 'The Gravity Forms plugin is required in order to run Gravity Forms Braintree Payments.']);
 		$checker->setRequiredExtensions(['xmlwriter', 'openssl', 'dom', 'hash', 'curl']);
-		$checker->setRequiredPlugins(['gravityforms/gravityforms.php'=>['ver'=>'2.4', 'install_link'=>'https://www.gravityforms.com/pricing/']]);
+		$checker->setRequiredPlugins(['gravityforms/gravityforms.php'=>['min_version'=>'2.4', 'install_link'=>'https://rocketgenius.pxf.io/c/1331556/445235/7938', 'name'=>'Gravity Forms']]);
 		//$checker->setDeactivatePlugins([self::$plugin_base_file]);
 		if($checker->check()===true) {
 			$this->init();
diff --git a/includes/angelleye-plugin-requirement-checker.php b/includes/angelleye-plugin-requirement-checker.php
index 2e51569..84422fd 100644
--- a/includes/angelleye-plugin-requirement-checker.php
+++ b/includes/angelleye-plugin-requirement-checker.php
@@ -71,21 +71,27 @@ public function check( $force_check = false ) {
 				require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
 				$all_plugins = get_plugins();
 				$active_plugins = get_option('active_plugins');
+				$install_needed_plugins = [];
 				foreach ($this->required_plugins as $single_plugin => $plugin_options){
 					if(in_array($single_plugin, $active_plugins)){
-						if(isset($plugin_options['ver'])) {
-							$min_version_required = $plugin_options['ver'];
+						if(isset($plugin_options['min_version'])) {
+							$min_version_required = $plugin_options['min_version'];
 							if ( version_compare( $all_plugins[ $single_plugin ]['Version'], $min_version_required, '<' ) ) {
-								$this->errors_list[] = 'You have ' . $all_plugins[ $single_plugin ]['Name'] . ' -  Version: ' . $all_plugins[ $single_plugin ]['Version'] . ' active, we require min ' . $all_plugins[ $single_plugin ]['Name'] . ' - Version: ' . $min_version_required . ' to run the ' . $this->plugin_name;
+								$this->errors_list[] = 'You have ' . $all_plugins[ $single_plugin ]['Name'] . ' -  Version: ' . $all_plugins[ $single_plugin ]['Version'] . ' installed, '.$this->plugin_name.' requires min ' . $all_plugins[ $single_plugin ]['Name'] . ' - Version: ' . $min_version_required . ' to function properly';
 							}
 						}
-					}else if(isset($all_plugins[$single_plugin])) {
-						$this->errors_list[] = 'Please activate '.$all_plugins[$single_plugin]['Name'].' plugin to run the '.$this->plugin_name;
+					} else if(isset($all_plugins[$single_plugin])) {
+						$this->errors_list[] = 'Please  activate the '.$all_plugins[$single_plugin]['Name'].' plugin to run the '.$this->plugin_name;
 					} else{
 						if(isset($plugin_options['install_link']))
-							$this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.';
+							$install_needed_plugins[] = ''.$plugin_options['name'].'';
 						else
-							$this->errors_list[] = 'Please install '.$all_plugins[$single_plugin]['Name'].' plugin.';
+							$install_needed_plugins[] = $plugin_options['name'];
+					}
+				}
+				if(count($install_needed_plugins)){
+					foreach ( $install_needed_plugins as $install_needed_plugin ) {
+						$this->errors_list[] = sprintf(__('Please install %s to continue.'), $install_needed_plugin);
 					}
 				}
 			}
@@ -112,14 +118,14 @@ public function check( $force_check = false ) {
 			}
 		}
 
-		public function showAdminNotice(  ) {
+		public function showAdminNotice() {
 
 			echo '

'.(in_array($this->base_plugin_file, $this->deactivate_plugins)? - $this->plugin_name.' plugin has been deactivated due to following errors.': - $this->plugin_name.' plugin is inactive due to following errors.').'

+ 'The '.$this->plugin_name.' plugin will not function due to the following:': + $this->plugin_name.' plugin is deactivated due to following errors.').'

'.implode('
', $this->errors_list).'

-
'; + '; if(count($this->deactivate_plugins)){ require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); foreach ($this->deactivate_plugins as $single_plugin_basename){ @@ -133,6 +139,11 @@ public function showAdminNotice( ) { } } + /** + * Run custom action when another plugin is deactivated - Deprecated + * @param $new_value + * @param $old_value + */ public function checkPluginDeactivation( $new_value, $old_value ) { if($this->check(true)!== true){ require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); @@ -148,7 +159,7 @@ public function checkPluginDeactivation( $new_value, $old_value ) { * @return string $url action url */ function pluginActionLink( $plugin, $action = 'activate' ) { - if ( strpos( $plugin, '/' ) ) { + if ( strpos( $plugin, '/' ) ) { $plugin = str_replace( '\/', '%2F', $plugin ); } $url = sprintf( admin_url( 'plugins.php?action=' . $action . '&plugin=%s&plugin_status=all&paged=1&s' ), $plugin ); From 98a30baaceca6a29947e53610936d21085c368a3 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Wed, 13 May 2020 23:29:11 +0530 Subject: [PATCH 73/99] Added the account number verification field and message updates, GFB-17 --- assets/js/angelleye-braintree-ach-cc.js | 51 ++++++----- ...-angelleye-gravity-braintree-ach-field.php | 89 +++++++++++-------- ...eye-gravity-braintree-ach-toggle-field.php | 43 ++++++++- lib/class.plugify-gform-braintree.php | 4 +- 4 files changed, 126 insertions(+), 61 deletions(-) diff --git a/assets/js/angelleye-braintree-ach-cc.js b/assets/js/angelleye-braintree-ach-cc.js index f5b95af..292b8c4 100644 --- a/assets/js/angelleye-braintree-ach-cc.js +++ b/assets/js/angelleye-braintree-ach-cc.js @@ -48,6 +48,7 @@ jQuery(document).ready(function ($) { } var account_number = form.find('.ginput_account_number').val(); + var account_number_verification = form.find('.ginput_account_number_verification').val(); var account_type = form.find('.ginput_account_type').val(); var routing_number = form.find('.ginput_routing_number').val(); var account_holdername = form.find('.ginput_account_holdername').val(); @@ -58,44 +59,52 @@ jQuery(document).ready(function ($) { var region = form.find('.ginput_container_address .address_state input[type=text]').val(); var postalCode = form.find('.ginput_container_address .address_zip input[type=text]').val(); + var address_validation_errors = []; if(streetAddress==''){ - alert('Please enter street address'); - return; + address_validation_errors.push('Please enter a street address.'); } if(locality==''){ - alert('Please enter your city'); - return; + address_validation_errors.push('Please enter your city.'); } if(region==''){ - alert('Please enter your state'); - return; + address_validation_errors.push('Please enter your state.'); } if(postalCode==''){ - alert('Please enter your Zip/Postal Code'); - return; + address_validation_errors.push('Please enter your postal code.'); } - if(account_number=='' || routing_number=='' || isNaN(account_number) || isNaN(routing_number)){ - alert('Please enter valid account number and routing number'); + if(address_validation_errors.length){ + alert(address_validation_errors.join('\n')); return; } + var achform_validation_errors = []; + if(routing_number=='' || isNaN(routing_number) || account_number=='' || isNaN(account_number)){ + achform_validation_errors.push('Please enter a valid routing and account number.') + } + if(account_type==''){ - alert('Please select account type.'); - return; + achform_validation_errors.push('Please select your account type.') } if(account_holdername==''){ - alert('Please enter account holder name.'); - return; + achform_validation_errors.push('Please enter the account holder name.'); + }else { + var account_holder_namebreak = account_holdername.split(' '); + if (account_type == 'S' && account_holder_namebreak.length < 2) { + achform_validation_errors.push('Please enter the account holder first and last name.'); + } + } + + if(account_number !== account_number_verification){ + achform_validation_errors.push('Account Number and Account Number Verification field should be same.'); } - var account_holder_namebreak = account_holdername.split(' '); - if(account_type=='S' && account_holder_namebreak.length<2){ - alert('Please enter account holder first name and last name.'); + if(achform_validation_errors.length){ + alert(achform_validation_errors.join('\n')); return; } @@ -116,7 +125,7 @@ jQuery(document).ready(function ($) { paypal: true }, function (err, dataCollectorInstance) { if (err) { - alert('We are unable to validate your computer request, please try again.'); + alert('We are unable to validate your system, please try again.'); resetButtonLoading(submitbtn, curlabel); console.error('dataCollectorError',err); return; @@ -128,7 +137,7 @@ jQuery(document).ready(function ($) { client: clientInstance }, function (usBankAccountErr, usBankAccountInstance) { if (usBankAccountErr) { - alert('There was an error in initating bank request, Please try again.'); + alert('There was an error initiating the bank request. Please try again.'); resetButtonLoading(submitbtn, curlabel); console.error('usBankAccountErr',usBankAccountErr); return; @@ -162,9 +171,9 @@ jQuery(document).ready(function ($) { if (tokenizeErr) { var errormsg = tokenizeErr['details']['originalError']['details']['originalError'][0]['message']; if (errormsg.indexOf("Variable 'zipCode' has an invalid value") != -1) - alert('Please enter valid zip code.'); + alert('Please enter valid postal code.'); else if (errormsg.indexOf("Variable 'state' has an invalid value") != -1) - alert('Please enter valid 2 Char State/Region code.'); + alert('Please enter valid state code. (e.g.: CA)'); else alert(errormsg); diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index b9d9d38..586313a 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -111,43 +111,30 @@ public function get_field_input( $form, $value = '', $entry = null ) { } - $tabindex = $this->get_tabindex(); - $account_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' ); - $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; - $account_number_label = rgar( $account_number_field_input, 'customLabel' ) != '' ? $account_number_field_input['customLabel'] : __( 'Account Number', 'gravity-forms-braintree' ); - $account_number_label = gf_apply_filters( array( 'gform_1', $form_id ), $account_number_label, $form_id ); - - $account_number_placeholder = $this->get_input_placeholder_attribute( $account_number_field_input ); - if ( $is_sub_label_above ) { - $account_field = " - - - "; - } else { - $account_field = " - - - "; - } - $tabindex = $this->get_tabindex(); $account_type_field_input = GFFormsModel::get_input( $this, $this->id . '.2' ); $account_type_options = $this->getAccountTypeSelectOptions( $account_type ); + + $account_types = $this->getAccountTypeList(); + //$radio_buttons = []; + //foreach ($account_types as $ac_key => $ac_label) + // $radio_buttons[]= ""; + $account_type_label = rgar( $account_type_field_input, 'customLabel' ) != '' ? $account_type_field_input['customLabel'] : __( 'Account Type', 'gravity-forms-braintree' ); $account_type_label = gf_apply_filters( array( 'gform_accounttype', $form_id ), $account_type_label, $form_id ); if ( $is_sub_label_above ) { - $account_type_field = " - - {$account_type_options} "; } else { - $account_type_field = " - {$account_type_options} - + "; } @@ -159,17 +146,49 @@ public function get_field_input( $form, $value = '', $entry = null ) { $routing_number_placeholder = $this->get_input_placeholder_attribute( $routing_number_field_input ); if ( $is_sub_label_above ) { - $routing_field = " - - + $routing_field = " + + "; } else { - $routing_field = " - - + $routing_field = " + + "; } + $tabindex = $this->get_tabindex(); + $account_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' ); + $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; + $account_number_label = rgar( $account_number_field_input, 'customLabel' ) != '' ? $account_number_field_input['customLabel'] : __( 'Account Number', 'gravity-forms-braintree' ); + $account_number_label = gf_apply_filters( array( 'gform_1', $form_id ), $account_number_label, $form_id ); + + $account_number_placeholder = $this->get_input_placeholder_attribute( $account_number_field_input ); + if ( $is_sub_label_above ) { + $account_field = " + + + "; + } else { + $account_field = " + + + "; + } + + $account_number_verification_field = ''; + if ( $is_sub_label_above ) { + $account_number_verification_field = " + + + "; + } else { + $account_number_verification_field = " + + + "; + } + $tabindex = $this->get_tabindex(); $account_holder_name_field_input = GFFormsModel::get_input( $this, $this->id . '.4' ); $account_holder_name_label = rgar( $account_holder_name_field_input, 'customLabel' ) != '' ? $account_holder_name_field_input['customLabel'] : __( 'Account Holder Name', 'gravity-forms-braintree' ); @@ -188,7 +207,7 @@ public function get_field_input( $form, $value = '', $entry = null ) { "; } - return "
" . $account_field . $account_type_field . $routing_field . $account_holder_name_field . '
'; + return "
" . $account_type_field. $account_holder_name_field . $routing_field . $account_field . $account_number_verification_field . '
'; } @@ -437,14 +456,12 @@ public function get_value_entry_detail( $value, $currency = '', $use_text = fals */ public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) { list( $input_token, $field_id_token, $input_id ) = rgexplode( '_', $input_name, 3 ); - /*if ( $input_id == '1' ) { + if ( $input_id == '1' || $input_id == '3' ) { $value = str_replace( ' ', '', $value ); $card_number_length = strlen( $value ); $value = substr( $value, - 4, 4 ); $value = str_pad( $value, $card_number_length, 'X', STR_PAD_LEFT ); - } elseif ( $input_id == '3' ) { - $value = rgpost( "input_{$field_id_token}_3" ); - }*/ + } return $this->sanitize_entry_value( $value, $form['id'] ); } diff --git a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php index a0c6b0f..33f988a 100644 --- a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php @@ -126,13 +126,52 @@ public function get_value_submission( $field_values, $get_from_post_global_var = return $value; } + /** + * Format the value on entry detail page + * @param array|string $value + * @param string $currency + * @param bool $use_text + * @param string $format + * @param string $media + * + * @return string + */ public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) { - if ( is_array( $value ) ) { $selected_method = trim( rgget( $this->id . '.1', $value ) ); - return$selected_method=='braintree_ach' ? 'Braintree ACH Direct Debit' : 'Credit Card'; + return $selected_method=='braintree_ach' ? 'Braintree ACH Direct Debit' : 'Credit Card'; } else { return ''; } } + + /** + * Format the entry value for display on the entries list page. + * + * Return a value that's safe to display on the page. + * + * @param string|array $value The field value. + * @param array $entry The Entry Object currently being processed. + * @param string $field_id The field or input ID currently being processed. + * @param array $columns The properties for the columns being displayed on the entry list page. + * @param array $form The Form Object currently being processed. + * + * @return string + */ + public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) { + + $allowable_tags = $this->get_allowable_tags( $form['id'] ); + + list( $input_id, $field_id ) = rgexplode( '.', $field_id, 2 ); + switch($field_id){ + case 1: + if($value=='braintree_ach') + $return = 'Braintree ACH Direct Debit'; + else if($value=='creditcard') + $return = 'Credit Card'; + break; + } + + return $return; + } } \ No newline at end of file diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 7d7687d..160dd98 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -135,9 +135,9 @@ public function ach_authorize( $feed, $submission_data, $form, $entry ) { $settings = $this->get_plugin_settings(); $response = getAngelleyeBraintreePaymentFields($form); $braintree_ach_field = $response['braintree_ach']; - $account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); + /*$account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); - $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' ); + $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' );*/ $account_holder_name = rgpost( 'input_' . $braintree_ach_field->id . '_4' ); $account_holder_name = explode(' ', $account_holder_name); From c524c7c7ff91151e075c8a74ab583bd775498c2e Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Wed, 13 May 2020 23:32:43 +0530 Subject: [PATCH 74/99] Custom toggle field form label updates, GFB-17 --- includes/class-angelleye-gravity-braintree-ach-toggle-field.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php index 33f988a..47c8d7d 100644 --- a/includes/class-angelleye-gravity-braintree-ach-toggle-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-toggle-field.php @@ -21,7 +21,7 @@ public function get_form_editor_field_title() { * @return array */ public function get_form_editor_button() { - return [ 'group' => 'pricing_fields', 'text' => 'Method Toggle' ]; + return [ 'group' => 'pricing_fields', 'text' => 'Payment Types' ]; } /** From b9177d31f0c9bf7e0f8249deada2528fde742489 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Wed, 13 May 2020 23:40:07 +0530 Subject: [PATCH 75/99] Update changelogs and version for v3.1.0 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 14 +++++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index a5df01b..ff1421a 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.0.2 + * Version: 3.1.0 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '3.0.2'; + public static $version = '3.1.0'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 160dd98..a93a083 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '3.0.2'; + protected $_version = '3.1.0'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index eba0ecd..c328351 100644 --- a/readme.txt +++ b/readme.txt @@ -2,11 +2,11 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree -Requires at least: 3.8 -Tested up to: 5.3.2 -Stable tag: 3.0.2 -License: GPLv2 or later -License URI: http://www.gnu.org/licenses/gpl-2.0.html +Requires at least: 5.0 +Tested up to: 5.4 +Stable tag: 3.1.0 +License: GPLv3 +License URI: https://www.gnu.org/licenses/gpl-3.0.html Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments @@ -64,6 +64,10 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.1.0 - 05.13.2020 = +* Feature - Added Braintree ACH Direct Debit Payment Gateway ([GFB-17](https://github.com/angelleye/gravity-forms-braintree/pull/25)) +* Feature - Added custom plugin requirement checker to validate server configuration ([GFB-22](https://github.com/angelleye/gravity-forms-braintree/pull/24)) + = 3.0.2 - 05.04.2020 = * Fix - Resolved the issue with PHP Version comparison ([GFB-21](https://github.com/angelleye/gravity-forms-braintree/pull/23)) From 0d1ecccf9ad57dfc197c4019b6ed9d888d5cf588 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 04:08:01 +0530 Subject: [PATCH 76/99] Braintree ACH + CC form compatibility added with custom toggle options, GFB-25 --- assets/js/angelleye-braintree-ach-cc.js | 2 +- .../angelleye-gravity-braintree-helper.php | 59 +++++++ ...-angelleye-gravity-braintree-ach-field.php | 22 +-- lib/class.plugify-gform-braintree.php | 154 +++++++++--------- 4 files changed, 147 insertions(+), 90 deletions(-) diff --git a/assets/js/angelleye-braintree-ach-cc.js b/assets/js/angelleye-braintree-ach-cc.js index 292b8c4..8af37b0 100644 --- a/assets/js/angelleye-braintree-ach-cc.js +++ b/assets/js/angelleye-braintree-ach-cc.js @@ -41,7 +41,7 @@ jQuery(document).ready(function ($) { var selectedradio = form.find('.gform_payment_method_options input[type=radio]:checked').val(); var check_if_ach_form = form.find('.ginput_ach_form_container'); - if(check_if_ach_form.length && (typeof selectedradio ==='undefined' || selectedradio === 'braintree_ach')){ + if(check_if_ach_form.length && (selectedradio === 'braintree_ach' || check_if_ach_form.closest('.gfield').css('display')!=='none')){ if(form.find('.ginput_container_address').length==0){ alert('ACH payment requires billing address fields, so please include Billing Address field in your Gravity form.'); return; diff --git a/includes/angelleye-gravity-braintree-helper.php b/includes/angelleye-gravity-braintree-helper.php index 4b02794..97bf7f9 100644 --- a/includes/angelleye-gravity-braintree-helper.php +++ b/includes/angelleye-gravity-braintree-helper.php @@ -18,6 +18,65 @@ function getAngelleyeBraintreePaymentFields($form){ return $response; } +function getAngelleyeBraintreePaymentMethod($form){ + $selected_method = ''; + $response = getAngelleyeBraintreePaymentFields($form); + + //This means customer is using our toggle button + if($response['braintree_ach_cc_toggle'] !== false){ + $selected_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); + }else { + if($response['creditcard']!==false){ + if(isset($response['creditcard']['conditionalLogic']) && is_array($response['creditcard']['conditionalLogic']) && count($response['creditcard']['conditionalLogic'])){ + $conditionalLogic = $response['creditcard']['conditionalLogic']; + if($conditionalLogic['actionType'] == 'show'){ + foreach ( $conditionalLogic['rules'] as $rule ) { + if($rule['operator'] == 'is') { + $fieldId = $rule['fieldId']; + $isValue = $rule['value']; + $selected_radio_value = rgpost( 'input_' . $fieldId ); + + if($selected_radio_value == $isValue){ + $selected_method = 'creditcard'; + break; + } + } + } + } + + } + } + + if($selected_method=='' && $response['braintree_ach'] !== false){ + if(isset($response['braintree_ach']['conditionalLogic']) && is_array($response['braintree_ach']['conditionalLogic']) && count($response['braintree_ach']['conditionalLogic'])){ + $conditionalLogic = $response['braintree_ach']['conditionalLogic']; + if($conditionalLogic['actionType'] == 'show'){ + foreach ( $conditionalLogic['rules'] as $rule ) { + if($rule['operator'] == 'is') { + $fieldId = $rule['fieldId']; + $isValue = $rule['value']; + $selected_radio_value = rgpost( 'input_' . $fieldId ); + if($selected_radio_value == $isValue){ + $selected_method = 'braintree_ach'; + break; + } + } + } + } + } + } + + if($selected_method == '' && $response['creditcard']!==false){ + $selected_method = 'creditcard'; + }else if($selected_method == '' && $response['braintree_ach']!==false){ + $selected_method = 'braintree_ach'; + } + + } + return $selected_method; +} + + /** * This is to setup default values for Custom Toggle and ACH form fields in admin panel */ diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index 586313a..a48e4df 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -4,6 +4,7 @@ class Angelleye_Gravity_Braintree_ACH_Field extends GF_Field { + private $selected_payment_method = ''; /** * @var string $type The field type. */ @@ -260,6 +261,11 @@ public function is_value_submission_empty( $form_id ) { */ function customCCValidation($validation_result){ $form = $validation_result['form']; + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); + + if($this->selected_payment_method !== 'braintree_ach') + return $validation_result; + $failed_validation = 0; if(isset($form['fields'])) { @@ -300,13 +306,9 @@ public function __construct( $data = array() ) { public function validate( $value, $form ) { //check if toggle field exist - $selected_payment_method = 'braintree_ach'; - $response = getAngelleyeBraintreePaymentFields($form); - if($response['braintree_ach_cc_toggle']!==false){ - $selected_payment_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); - } + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - if($selected_payment_method!=='braintree_ach') { + if($this->selected_payment_method!=='braintree_ach') { return; } @@ -347,10 +349,10 @@ public function validate( $value, $form ) { public function get_value_submission( $field_values, $get_from_post_global_var = true ) { if ( $get_from_post_global_var ) { - $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( $this->inputs[0], 'name' ), $field_values, true ); - $value[ $this->id . '.2' ] = $this->get_input_value_submission( 'input_' . $this->id . '_2', rgar( $this->inputs[1], 'name' ), $field_values, true ); - $value[ $this->id . '.3' ] = $this->get_input_value_submission( 'input_' . $this->id . '_3', rgar( $this->inputs[2], 'name' ), $field_values, true ); - $value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', rgar( $this->inputs[3], 'name' ), $field_values, true ); + $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( @$this->inputs[0], 'name' ), $field_values, true ); + $value[ $this->id . '.2' ] = $this->get_input_value_submission( 'input_' . $this->id . '_2', rgar( @$this->inputs[1], 'name' ), $field_values, true ); + $value[ $this->id . '.3' ] = $this->get_input_value_submission( 'input_' . $this->id . '_3', rgar( @$this->inputs[2], 'name' ), $field_values, true ); + $value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', rgar( @$this->inputs[3], 'name' ), $field_values, true ); } else { $value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var ); } diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index a93a083..9f75033 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -132,85 +132,90 @@ public function ach_authorize( $feed, $submission_data, $form, $entry ) { $gateway = $this->getBraintreeGateway(); if( $gateway !== false ) { - $settings = $this->get_plugin_settings(); - $response = getAngelleyeBraintreePaymentFields($form); - $braintree_ach_field = $response['braintree_ach']; - /*$account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); - $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); - $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' );*/ - $account_holder_name = rgpost( 'input_' . $braintree_ach_field->id . '_4' ); - - $account_holder_name = explode(' ', $account_holder_name); - /** - * Create customer in Braintree - */ - $customer_request = [ - 'firstName' => @$account_holder_name[0], - 'lastName' => end($account_holder_name), - ]; - $this->log_debug( "Braintree_ACH_Customer::create REQUEST => " . print_r( $customer_request, 1 ) ); - $customer_result = $gateway->customer()->create( $customer_request ); - $this->log_debug( "Braintree_ACH_Customer::create RESPONSE => " . print_r( $customer_result, 1 ) ); - - if ( $customer_result->success ) { - $payment_method_request = [ - 'customerId' => $customer_result->customer->id, - 'paymentMethodNonce' => $ach_token, - 'options' => [ - 'usBankAccountVerificationMethod' => Braintree\Result\UsBankAccountVerification::NETWORK_CHECK - ] + try { + $settings = $this->get_plugin_settings(); + $response = getAngelleyeBraintreePaymentFields( $form ); + $braintree_ach_field = $response['braintree_ach']; + /*$account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); + $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); + $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' );*/ + $account_holder_name = rgpost( 'input_' . $braintree_ach_field->id . '_4' ); + + $account_holder_name = explode( ' ', $account_holder_name ); + /** + * Create customer in Braintree + */ + $customer_request = [ + 'firstName' => @$account_holder_name[0], + 'lastName' => end( $account_holder_name ), ]; - - $this->log_debug( "Braintree_ACH_PaymentRequest::create REQUEST => " . print_r( $payment_method_request, 1 ) ); - $payment_method_response = $gateway->paymentMethod()->create( $payment_method_request ); - $this->log_debug( "Braintree_ACH_PaymentRequest::create RESPONSE => " . print_r( $payment_method_response, 1 ) ); - - if(isset($payment_method_response->paymentMethod->token)) { - - $sale_request = [ - 'amount' => $payment_amount, - 'paymentMethodToken' => $payment_method_response->paymentMethod->token, - 'deviceData' => $ach_device_corelation, + $this->log_debug( "Braintree_ACH_Customer::create REQUEST => " . print_r( $customer_request, 1 ) ); + $customer_result = $gateway->customer()->create( $customer_request ); + $this->log_debug( "Braintree_ACH_Customer::create RESPONSE => " . print_r( $customer_result, 1 ) ); + + if ( $customer_result->success ) { + $payment_method_request = [ + 'customerId' => $customer_result->customer->id, + 'paymentMethodNonce' => $ach_token, 'options' => [ - 'submitForSettlement' => true + 'usBankAccountVerificationMethod' => Braintree\Result\UsBankAccountVerification::NETWORK_CHECK ] ]; - $this->log_debug( "Braintree_ACH_Transaction::sale REQUEST => " . print_r( $sale_request, 1 ) ); - $sale_response = $gateway->transaction()->sale($sale_request); - $this->log_debug( "Braintree_ACH_Transaction::sale RESPONSE => " . print_r( $sale_response, 1 ) ); - - if ( $sale_response->success ) { - do_action('angelleye_gravity_forms_response_data', $sale_response, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree_ach'); - $authorization['is_authorized'] = true; - $authorization['error_message'] = ''; - $authorization['transaction_id'] = $sale_response->transaction->id; - - $authorization['captured_payment'] = array( - 'is_success' => true, - 'transaction_id' => $sale_response->transaction->id, - 'amount' => $sale_response->transaction->amount, - 'error_message' => '', - 'payment_method' => 'Braintree ACH' - ); - - $this->log_debug( "Braintree_ACH::SUCCESS"); - } else { - if( isset( $sale_response->transaction->processorResponseText ) ) { - $authorization['error_message'] = sprintf( 'Your bank did not authorized the transaction: %s.', $sale_response->transaction->processorResponseText); - }else { - $authorization['error_message'] = sprintf( 'Your bank declined the transaction, please try again or contact bank.'); + $this->log_debug( "Braintree_ACH_PaymentRequest::create REQUEST => " . print_r( $payment_method_request, 1 ) ); + $payment_method_response = $gateway->paymentMethod()->create( $payment_method_request ); + $this->log_debug( "Braintree_ACH_PaymentRequest::create RESPONSE => " . print_r( $payment_method_response, 1 ) ); + + if ( isset( $payment_method_response->paymentMethod->token ) ) { + + $sale_request = [ + 'amount' => $payment_amount, + 'paymentMethodToken' => $payment_method_response->paymentMethod->token, + 'deviceData' => $ach_device_corelation, + 'options' => [ + 'submitForSettlement' => true + ] + ]; + + $this->log_debug( "Braintree_ACH_Transaction::sale REQUEST => " . print_r( $sale_request, 1 ) ); + $sale_response = $gateway->transaction()->sale( $sale_request ); + $this->log_debug( "Braintree_ACH_Transaction::sale RESPONSE => " . print_r( $sale_response, 1 ) ); + + if ( $sale_response->success ) { + do_action( 'angelleye_gravity_forms_response_data', $sale_response, $submission_data, '16', ( strtolower( $settings['environment'] ) == 'sandbox' ) ? true : false, false, 'braintree_ach' ); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $sale_response->transaction->id; + + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $sale_response->transaction->id, + 'amount' => $sale_response->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Braintree ACH' + ); + + $this->log_debug( "Braintree_ACH::SUCCESS" ); + } else { + if ( isset( $sale_response->transaction->processorResponseText ) ) { + $authorization['error_message'] = sprintf( 'Your bank did not authorized the transaction: %s.', $sale_response->transaction->processorResponseText ); + } else { + $authorization['error_message'] = sprintf( 'Your bank declined the transaction, please try again or contact bank.' ); + } + $this->log_debug( "Braintree_ACH::FAILED_ERROR" ); } - $this->log_debug( "Braintree_ACH::FAILED_ERROR"); + } else { + $authorization['error_message'] = __( 'We are unable to authorize bank account, This may have happened due to expired token, please try again.', 'gravity-forms-braintree' ); } } else { - $authorization['error_message'] = __('We are unable to authorize bank account, This may have happened due to expired token, please try again.', 'gravity-forms-braintree'); + $authorization['error_message'] = __( 'Unable to proceed with the transaction due to invalid name.', 'gravity-forms-braintree' ); } - } else { - $authorization['error_message'] = __('Unable to proceed with the transaction due to invalid name.', 'gravity-forms-braintree'); + }catch (Exception $exception){ + $this->log_debug( "Braintree_ACH::EXCEPTION: ".$exception->getTraceAsString() ); + $exception['error_message'] = __('An internal error occurred, Please try later. ERROR: '.$exception->getMessage()); } - return $authorization; + } $this->log_debug( "Braintree_ACH::FAILED"); @@ -283,18 +288,9 @@ public function get_validation_result( $validation_result, $authorization_result */ public function authorize( $feed, $submission_data, $form, $entry ) { - $selected_payment_method = 'braintree_ach'; - $response = getAngelleyeBraintreePaymentFields($form); - if($response['braintree_ach_cc_toggle']!==false){ - $selected_payment_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); - }else { - //This means there was no toggle button, Need to identify based on the fields - if($response['creditcard']!==false) - $selected_payment_method = 'creditcard'; - } + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - $this->selected_payment_method = $selected_payment_method; - if($selected_payment_method=='braintree_ach'){ + if($this->selected_payment_method == 'braintree_ach'){ return $this->ach_authorize($feed, $submission_data, $form, $entry); } From 9223b8882b209176581b395d33f0daeae81b208b Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 05:16:17 +0530 Subject: [PATCH 77/99] Adjustment with Entry values on entry detail page and input field actions defined, GFB-25 --- .../angelleye-gravity-braintree-helper.php | 46 +++++++++---------- ...-angelleye-gravity-braintree-ach-field.php | 4 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/includes/angelleye-gravity-braintree-helper.php b/includes/angelleye-gravity-braintree-helper.php index 97bf7f9..d96de7f 100644 --- a/includes/angelleye-gravity-braintree-helper.php +++ b/includes/angelleye-gravity-braintree-helper.php @@ -81,28 +81,26 @@ function getAngelleyeBraintreePaymentMethod($form){ * This is to setup default values for Custom Toggle and ACH form fields in admin panel */ -add_action( 'gform_loaded', function (){ - add_action( 'gform_editor_js_set_default_values', 'gravityFormSetDefaultValueOnDropin' ); - function gravityFormSetDefaultValueOnDropin() { - ?> - case "braintree_ach" : - if (!field.label) - field.label = ; - var accNumber, accType, routingNumber, accName; +add_action( 'gform_editor_js_set_default_values', 'gravityFormSetDefaultValueOnDropin' ); +function gravityFormSetDefaultValueOnDropin() { + ?> + case "braintree_ach" : + if (!field.label) + field.label = ; + var accNumber, accType, routingNumber, accName; - accNumber = new Input(field.id + ".1", ); - accType = new Input(field.id + ".2", ); - routingNumber = new Input(field.id + ".3", ); - accName = new Input(field.id + ".4", ); - field.inputs = [accNumber, accType, routingNumber, accName]; - break; - case "braintree_ach_cc_toggle": - if (!field.label) - field.label = ; - var paymentMethodToggle; - paymentMethodToggle = new Input(field.id + ".1", ); - field.inputs = [paymentMethodToggle]; - break; - ); + accType = new Input(field.id + ".2", ); + routingNumber = new Input(field.id + ".3", ); + accName = new Input(field.id + ".4", ); + field.inputs = [accNumber, accType, routingNumber, accName]; + break; + case "braintree_ach_cc_toggle": + if (!field.label) + field.label = ; + var paymentMethodToggle; + paymentMethodToggle = new Input(field.id + ".1", ); + field.inputs = [paymentMethodToggle]; + break; + id . '.2', $value ) ); $routing_number = trim( rgget( $this->id . '.3', $value ) ); $account_holder_name = trim( rgget( $this->id . '.4', $value ) ); + if($account_number=='') + return 'N/A'; if($format=='html') - return "Account Number: $account_number
+ return "Account Number: $account_number
Account Type: ".($account_type=='s'?'Savings':'Checking')."
Routing Number: $routing_number
Account Holder: $account_holder_name
"; From 467294e1b2ab1fec55f3ee0468cc601686a9e218 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 05:32:21 +0530 Subject: [PATCH 78/99] Pass custom field mapping data with ACH Direct Debit payments, GFB-24 --- lib/class.plugify-gform-braintree.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index a93a083..40a14d7 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -176,6 +176,8 @@ public function ach_authorize( $feed, $submission_data, $form, $entry ) { ] ]; + $sale_request = apply_filters('angelleye_braintree_parameter', $sale_request, $submission_data, $form, $entry); + $this->log_debug( "Braintree_ACH_Transaction::sale REQUEST => " . print_r( $sale_request, 1 ) ); $sale_response = $gateway->transaction()->sale($sale_request); $this->log_debug( "Braintree_ACH_Transaction::sale RESPONSE => " . print_r( $sale_response, 1 ) ); From b7380fe5301a0fb5f1d590d9b817a0dece1e5275 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 05:37:29 +0530 Subject: [PATCH 79/99] Update changelog and version for v3.1.1 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index ff1421a..9c978c0 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.1.0 + * Version: 3.1.1 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '3.1.0'; + public static $version = '3.1.1'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index b75a6fd..d225b03 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '3.1.0'; + protected $_version = '3.1.1'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index c328351..16b9fdc 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 Tested up to: 5.4 -Stable tag: 3.1.0 +Stable tag: 3.1.1 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,10 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.1.1 - 05.14.2020 = +* Feature - Added Braintree ACH Direct Debit + CC compatibility with custom radio fields and conditions ([GFB-25](https://github.com/angelleye/gravity-forms-braintree/pull/26)) +* Feature - Pass custom field mapping data with ACH Direct Debit payments ([GFB-24](https://github.com/angelleye/gravity-forms-braintree/pull/27)) + = 3.1.0 - 05.13.2020 = * Feature - Added Braintree ACH Direct Debit Payment Gateway ([GFB-17](https://github.com/angelleye/gravity-forms-braintree/pull/25)) * Feature - Added custom plugin requirement checker to validate server configuration ([GFB-22](https://github.com/angelleye/gravity-forms-braintree/pull/24)) From 2c421497e51836489cb09220522181a3f272781c Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 14:18:22 +0530 Subject: [PATCH 80/99] Fixed the regression issue due to merge conflict related to payment method validation, GFB-27 --- .../class-angelleye-gravity-braintree-ach-field.php | 2 +- lib/class.plugify-gform-braintree.php | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index e23c85c..1c1c200 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -295,7 +295,7 @@ function customCCValidation($validation_result){ */ public function __construct( $data = array() ) { parent::__construct($data); - add_filter( 'gform_validation', [$this, 'customCCValidation'], 10 ); + add_filter( 'gform_validation', [$this, 'customCCValidation'], 50 ); } /** diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index d225b03..cadc5be 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -290,18 +290,9 @@ public function get_validation_result( $validation_result, $authorization_result */ public function authorize( $feed, $submission_data, $form, $entry ) { - $selected_payment_method = 'braintree_ach'; - $response = getAngelleyeBraintreePaymentFields($form); - if($response['braintree_ach_cc_toggle']!==false){ - $selected_payment_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); - }else { - //This means there was no toggle button, Need to identify based on the fields - if($response['creditcard']!==false) - $selected_payment_method = 'creditcard'; - } + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - $this->selected_payment_method = $selected_payment_method; - if($selected_payment_method=='braintree_ach'){ + if($this->selected_payment_method=='braintree_ach'){ return $this->ach_authorize($feed, $submission_data, $form, $entry); } From 533250017ad51e97a0e5c8e218d507162f95309f Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Thu, 14 May 2020 14:37:37 +0530 Subject: [PATCH 81/99] Updates changeload and version for v3.1.2 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 9c978c0..05c085a 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.1.1 + * Version: 3.1.2 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '3.1.1'; + public static $version = '3.1.2'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index cadc5be..b6a3595 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '3.1.1'; + protected $_version = '3.1.2'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index 16b9fdc..ec1fbe2 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 Tested up to: 5.4 -Stable tag: 3.1.1 +Stable tag: 3.1.2 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 3.1.2 - 05.14.2020 = +* Fix - Resolved Braintree ACH/CC form validation issuw with multiple Payment Methods ([GFB-27](https://github.com/angelleye/gravity-forms-braintree/pull/28)) + = 3.1.1 - 05.14.2020 = * Feature - Added Braintree ACH Direct Debit + CC compatibility with custom radio fields and conditions ([GFB-25](https://github.com/angelleye/gravity-forms-braintree/pull/26)) * Feature - Pass custom field mapping data with ACH Direct Debit payments ([GFB-24](https://github.com/angelleye/gravity-forms-braintree/pull/27)) From 038a4ba9eb1640037fff2e6cc58ea5926de8974e Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 1 Mar 2021 15:36:46 +0530 Subject: [PATCH 82/99] Add Braintree Subscription, GFB-31 --- angelleye-gravity-forms-braintree.php | 13 +- ...elleye-gravity-braintree-field-mapping.php | 4 +- .../angelleye-gravity-braintree-helper.php | 18 +- ...angelleye-gravity-braintree-creditcard.php | 119 +++++ lib/class.plugify-gform-braintree.php | 461 +++++++++++++++++- readme.txt | 7 +- 6 files changed, 595 insertions(+), 27 deletions(-) create mode 100644 includes/class-angelleye-gravity-braintree-creditcard.php diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 05c085a..5fb0d23 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 3.1.2 + * Version: 4.0 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '3.1.2'; + public static $version = '4.0'; public static function getInstance() { @@ -57,6 +57,13 @@ public function __construct() register_uninstall_hook( __FILE__, array(AngelleyeGravityBraintreeActivator::class,'Uninstall')); add_action('plugins_loaded', [$this, 'requirementCheck']); + add_action( 'wp_enqueue_scripts', [$this, 'enqueue_scripts']); + } + + + public function enqueue_scripts() { + wp_register_script('braintreegateway-dropin', "https://js.braintreegateway.com/web/dropin/1.26.0/js/dropin.min.js"); + wp_enqueue_script('braintreegateway-dropin'); } public function requirementCheck() { @@ -94,6 +101,7 @@ public function init() require_once $path . 'includes/class-angelleye-gravity-braintree-ach-toggle-field.php'; require_once $path . 'lib/angelleye-gravity-forms-payment-logger.php'; require_once $path . 'includes/angelleye-gravity-braintree-field-mapping.php'; + require_once $path . 'includes/class-angelleye-gravity-braintree-creditcard.php'; /** * Required functions @@ -111,6 +119,7 @@ public function init() */ GF_Fields::register( new Angelleye_Gravity_Braintree_ACH_Field() ); GF_Fields::register( new Angelleye_Gravity_Braintree_ACH_Toggle_Field() ); + GF_Fields::register( new Angelleye_Gravity_Braintree_CreditCard_Field() ); AngellEYE_GForm_Braintree_Payment_Logger::instance(); } diff --git a/includes/angelleye-gravity-braintree-field-mapping.php b/includes/angelleye-gravity-braintree-field-mapping.php index 6ba2570..c3d98bb 100644 --- a/includes/angelleye-gravity-braintree-field-mapping.php +++ b/includes/angelleye-gravity-braintree-field-mapping.php @@ -42,7 +42,7 @@ public function isCreditCardFieldExist($id) $get_form = GFAPI::get_form($id); if(isset($get_form['fields'])) { foreach ($get_form['fields'] as $single_field) { - if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach') { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type=='braintree_credit_card' ) { return true; } } @@ -123,7 +123,7 @@ public function mapGravityBraintreeFields($args, $submission_data, $form, $entry function addNoticeToCreditCardForm( $field_content, $field, $value, $lead_id, $form_id ) { if(is_admin()) { - if ($field->type == 'creditcard') { + if ($field->type == 'creditcard' || $field->type == 'braintree_credit_card') { //echo ($field_content); die; $first_label_position = strpos($field_content, ' false, 'braintree_ach' => false, - 'braintree_ach_cc_toggle' => false + 'braintree_ach_cc_toggle' => false, + 'braintree_credit_card' => false ]; if(isset($form['fields'])) { foreach ($form['fields'] as $single_field) { - if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type == 'braintree_ach_cc_toggle') { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type == 'braintree_ach_cc_toggle' || $single_field->type=='braintree_credit_card') { $response[$single_field->type] = $single_field; } } @@ -25,7 +26,7 @@ function getAngelleyeBraintreePaymentMethod($form){ //This means customer is using our toggle button if($response['braintree_ach_cc_toggle'] !== false){ $selected_method = rgpost( 'input_' . $response['braintree_ach_cc_toggle']->id . '_1' ); - }else { + } else { if($response['creditcard']!==false){ if(isset($response['creditcard']['conditionalLogic']) && is_array($response['creditcard']['conditionalLogic']) && count($response['creditcard']['conditionalLogic'])){ $conditionalLogic = $response['creditcard']['conditionalLogic']; @@ -68,11 +69,14 @@ function getAngelleyeBraintreePaymentMethod($form){ if($selected_method == '' && $response['creditcard']!==false){ $selected_method = 'creditcard'; - }else if($selected_method == '' && $response['braintree_ach']!==false){ + } else if($selected_method == '' && $response['braintree_ach']!==false){ $selected_method = 'braintree_ach'; + } else if($selected_method == '' && $response['braintree_credit_card']!==false){ + $selected_method = 'braintree_credit_card'; } } + return $selected_method; } @@ -102,5 +106,11 @@ function gravityFormSetDefaultValueOnDropin() { paymentMethodToggle = new Input(field.id + ".1", ); field.inputs = [paymentMethodToggle]; break; + case "braintree_credit_card": + if (!field.label) + field.label = ; + var braintreeCC = new Input(field.id + ".1", ); + field.inputs = [braintreeCC]; + break; 'pricing_fields', 'text' => 'Braintree CC' ]; + } + + /** + * The settings which should be available on the field in the form editor. + * + * @return array + */ + function get_form_editor_field_settings() { + return [ + 'label_setting', + 'admin_label_setting', + 'description_setting', + 'error_message_setting', + 'css_class_setting', + 'conditional_logic_field_setting', + 'rules_setting', + 'input_placeholders_setting', + 'label_placement_setting' + ]; + } + + /** + * Returns the field inner markup. + * + * @param array $form The Form Object currently being processed. + * @param string $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission. + * @param null $entry Null or the Entry Object currently being edited. + * + * @return false|string + * @throws \Braintree\Exception\Configuration + */ + public function get_field_input( $form, $value = '', $entry = null ) { + + $is_entry_detail = $this->is_entry_detail(); + $is_form_editor = $this->is_form_editor(); + + $form_id = $form['id']; + $id = intval( $this->id ); + $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; + $form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id; + + $Plugify_GForm_Braintree = new Plugify_GForm_Braintree(); + $gateway = $Plugify_GForm_Braintree->getBraintreeGateway(); + $clientToken = $gateway->clientToken()->generate(); + + ob_start(); + + ?> +
+
+ +
+ + type == 'creditcard' || $single_field->type=='braintree_ach') { + if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type=='braintree_credit_card') { return true; } } @@ -222,7 +224,6 @@ public function ach_authorize( $feed, $submission_data, $form, $entry ) { $this->log_debug( "Braintree_ACH::FAILED"); return false; - } /** @@ -267,6 +268,78 @@ public function get_validation_result( $validation_result, $authorization_result } + /** + * Braintree credit card Payment authorization + * @param $feed + * @param $submission_data + * @param $form + * @param $entry + * + * @return array|bool + * @throws \Braintree\Exception\Configuration + */ + public function braintree_cc_authorize( $feed, $submission_data, $form, $entry ) { + + $authorization = array( + 'is_authorized' => false, + 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'Your card could not be billed. Please ensure the details you entered are correct and try again.', 'gravity-forms-braintree' ) ), + 'transaction_id' => '', + 'captured_payment' => array( + 'is_success' => false, + 'error_message' => '', + 'transaction_id' => '', + 'amount' => $submission_data['payment_amount'] + ) + ); + + if(empty($_POST['payment_method_nonce'])) { + return $authorization; + } + + try { + + $settings = $this->get_plugin_settings(); + $gateway = $this->getBraintreeGateway(); + + $args = array( + 'amount' => $submission_data['payment_amount'], + 'paymentMethodNonce' => $_POST['payment_method_nonce'] + ); + + $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); + + if( $settings['settlement'] == 'Yes' ) { + $args['options']['submitForSettlement'] = 'true'; + } + + $result = $gateway->transaction()->sale($args); + + if( $result->success ) { + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree'); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $result->transaction->id; + + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $result->transaction->id, + 'amount' => $result->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Credit Card' + ); + + } else { + if( isset( $result->transaction->processorResponseText ) ) { + $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); + } + } + + } catch( Exception $e ) { + // Do nothing with exception object, just fallback to generic failure + } + + return $authorization; + } /** * After form has been submitted, send CC details to Braintree and ensure the card is going to work @@ -296,6 +369,9 @@ public function authorize( $feed, $submission_data, $form, $entry ) { return $this->ach_authorize($feed, $submission_data, $form, $entry); } + if( $this->selected_payment_method == 'braintree_credit_card' ) { + return $this->braintree_cc_authorize($feed, $submission_data, $form, $entry); + } // Prepare authorization response payload $authorization = array( @@ -360,15 +436,12 @@ public function authorize( $feed, $submission_data, $form, $entry ) { } else { - // Append gateway response text to error message if it exists. If it doesn't exist, a more hardcore // failure has occured and it won't do the user any good to see it other than a general error message if( isset( $result->transaction->processorResponseText ) ) { $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); } - } - } catch( Exception $e ) { // Do nothing with exception object, just fallback to generic failure @@ -379,9 +452,209 @@ public function authorize( $feed, $submission_data, $form, $entry ) { } return false; - } + public function process_capture( $authorization, $feed, $submission_data, $form, $entry ) { + + do_action( 'gform_braintree_post_capture', rgar( $authorization, 'is_authorized' ), rgars( $authorization, 'captured_payment/amount' ), $entry, $form, $this->_args_for_deprecated_hooks['config'], $this->_args_for_deprecated_hooks['aim_response'] ); + + return parent::process_capture( $authorization, $feed, $submission_data, $form, $entry ); + } + + /** + * Braintree Override this method to add integration code to the payment processor in order to create a subscription. + * + * This method is executed during the form validation process and allows the form submission process to fail with a + * validation error if there is anything wrong when creating the subscription. + * + * @param array $feed Current configured payment feed. + * @param array $submission_data Contains form field data submitted by the user as well as payment information + * (i.e. payment amount, setup fee, line items, etc...). + * @param array $form Current form array containing all form settings. + * @param array $entry Current entry array containing entry information (i.e data submitted by users). + * NOTE: the entry hasn't been saved to the database at this point, so this $entry + * object does not have the 'ID' property and is only a memory representation of the entry. + * + * @return array { + * Return an $subscription array + * @type bool $is_success If the subscription is successful. + * @type string $error_message The error message, if applicable. + * @type string $subscription_id The subscription ID. + * @type int $amount The subscription amount. + * @type array $captured_payment { + * If payment is captured, an additional array is created. + * @type bool $is_success If the payment capture is successful. + * @type string $error_message The error message, if any. + * @type string $transaction_id The transaction ID of the captured payment. + * @type int $amount The amount of the captured payment, if successful. + * } + * + * To implement an initial/setup fee for gateways that don't support setup fees as part of subscriptions, manually + * capture the funds for the setup fee as a separate transaction and send that payment information in the + * following 'captured_payment' array: + * + * 'captured_payment' => [ + * 'name' => 'Setup Fee', + * 'is_success' => true|false, + * 'error_message' => 'error message', + * 'transaction_id' => 'xxx', + * 'amount' => XX + * ] + * } + * @throws \Braintree\Exception\Configuration + */ + public function subscribe( $feed, $submission_data, $form, $entry ) { + + $authorization = array( + 'is_authorized' => false, + 'is_success' => false, + 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'Your card could not be billed. Please ensure the details you entered are correct and try again.', 'angelleye-gravity-forms-braintree' ) ), + ); + + if(empty($_POST['payment_method_nonce'])) { + return $authorization; + } + + $settings = $this->get_plugin_settings(); + $gateway = $this->getBraintreeGateway(); + + $args = array( + 'amount' => $submission_data['payment_amount'], + 'creditCard' => array( + 'number' => !empty($submission_data['card_number']) ? str_replace( array( '-', ' ' ), '', $submission_data['card_number'] ) : '', + 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), + 'cardholderName' => $submission_data['card_name'], + 'cvv' => $submission_data['card_security_code'] + ) + ); + + $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); + + $customerArgs = !empty($args['customer']) ? $args['customer'] : array(); + + $customer_id = $this->get_customer_id($customerArgs); + + $paymentMethod = $gateway->paymentMethod()->create([ + 'customerId' => $customer_id, + 'paymentMethodNonce' => $_POST['payment_method_nonce'] + ]); + + $fee_amount = !empty($submission_data['setup_fee']) ? $submission_data['setup_fee'] : 0; + $setup_fee_result = true; + + if ( ! empty( $fee_amount ) && $fee_amount > 0 ) { + + $feeArgs = array( + 'amount' => $fee_amount, + 'paymentMethodToken' => $paymentMethod->paymentMethod->token, + ); + + if( $settings['settlement'] == 'Yes' ) { + $feeArgs['options']['submitForSettlement'] = 'true'; + } + + $feeArgs = apply_filters('angelleye_braintree_parameter', $feeArgs, $submission_data, $form, $entry); + + $feeResult = $gateway->transaction()->sale($feeArgs); + + if( $feeResult->success ) { + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $feeResult->transaction->id, + 'amount' => $feeResult->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Credit Card' + ); + } else { + $setup_fee_result = false; + if( isset( $result->transaction->processorResponseText ) ) { + $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); + } + } + } + + if( $setup_fee_result ) { + + try { + $subscriptionArgs = array( + 'paymentMethodToken' => $paymentMethod->paymentMethod->token, + 'planId' => !empty($feed['meta']['subscriptionPlan']) ? $feed['meta']['subscriptionPlan'] : '', + 'price' => $submission_data['payment_amount'], + ); + + if ( $feed['meta']['recurringTimes'] == 0 ) { + $subscriptionArgs['neverExpires'] = true; + } else { + $subscriptionArgs['numberOfBillingCycles'] = $feed['meta']['recurringTimes']; + } + + if ( !empty($feed['meta']['trial_enabled']) ) { + $subscriptionArgs['trialDuration'] = ''; + $subscriptionArgs['trialDurationUnit'] = ''; + $subscriptionArgs['trialPeriod'] = true; + } else { + $subscriptionArgs['firstBillingDate'] = ''; + } + + $subscriptionArgs = apply_filters( 'angelleye_gravity_braintree_subscription_args', $subscriptionArgs ); + $subscription = $gateway->subscription()->create($subscriptionArgs); + + if($subscription->success) { + + $authorization['is_authorized'] = true; + $authorization['is_success'] = true; + $authorization['error_message'] = ''; + $authorization['paymentMethodToken'] = $subscription->subscription->paymentMethodToken; + $authorization['subscription_id'] = $subscription->subscription->id; + $authorization['amount'] = $subscription->subscription->price; + $authorization['subscription_trial_amount'] = $subscription->subscription->price; + $authorization['subscription_start_date'] = $subscription->subscription->firstBillingDate->date; + } + + } catch ( Exception $e ) { + + } + } + + return $authorization; + } + + /** + * Braintree override this method to add integration code to the payment processor in order to cancel a subscription. + * + * This method is executed when a subscription is canceled from the braintree Payment Gateway. + * + * @param array $entry Current entry array containing entry information (i.e data submitted by users). + * @param array $feed Current configured payment feed. + * + * @return bool Returns true if the subscription was cancelled successfully and false otherwise. + * + * @throws \Braintree\Exception\Configuration + */ + public function cancel( $entry, $feed ) { + + $gateway = $this->getBraintreeGateway(); + + $result = $gateway->subscription()->cancel($entry['transaction_id']); + + if($result->success) { + return true; + } + + return false; + } + + public function is_payment_gateway( $entry_id ) { + + if ( $this->is_payment_gateway ) { + return true; + } + + $gateway = gform_get_meta( $entry_id, 'payment_gateway' ); + + return in_array( $gateway, array( 'Braintree', $this->_slug ) ); + } + /** * Create and display feed settings fields. * @@ -402,19 +675,87 @@ public function feed_settings_fields () { // Remove the subscription option from transaction type dropdown $transaction_type = $this->get_field( 'transactionType', $settings ); - foreach( $transaction_type['choices'] as $index => $choice ) { - if( $choice['value'] == 'subscription' ) { - unset( $transaction_type['choices'][$index] ); - } - } + //foreach( $transaction_type['choices'] as $index => $choice ) { + //if( $choice['value'] == 'subscription' ) { + //unset( $transaction_type['choices'][$index] ); + //} + //} $settings = $this->replace_field( 'transactionType', $transaction_type, $settings ); + $settings = parent::remove_field( 'trial', $settings ); + + $createBraintreePlanUrl = $this->merchant_url('plans/new'); + $api_settings_field = array( + array( + 'name' => 'braintree_trial', + 'label' => esc_html__( 'Trial', 'angelleye-gravity-forms-braintree' ), + 'type' => 'braintree_trial', + 'hidden' => '', + 'tooltip' => '' + ), + array( + 'name' => 'subscriptionPlan', + 'label' => esc_html__( 'Plan', 'angelleye-gravity-forms-braintree' ), + 'type' => 'select', + 'choices' => $this->get_plans(), + 'required' => true, + 'tooltip' => sprintf(__('Plugin will fetch and display the subscription plans. Create the %splan%s in your Braintree account.','angelleye-gravity-forms-braintree'),'',''), + ), + ); + + $settings = $this->add_field_after( 'setupFee', $api_settings_field, $settings ); + // Return sanitized settings return $settings; } + public function merchant_url( $tab = 'plans') { + + $settings = $this->get_plugin_settings(); + + $braintreeUrl = '#'; + if( !empty($settings['merchant-id']) ) { + $environment = ! empty( $settings['environment'] ) ? strtolower( $settings['environment'] ) : 'sandbox'; + $environmentUrl = ( $environment == 'sandbox' ) ? 'sandbox.' : ''; + + $braintree_config = new \Braintree\Configuration( [ + 'environment' => strtolower( $settings['environment'] ), + 'merchantId' => $settings['merchant-id'], + 'publicKey' => $settings['public-key'], + 'privateKey' => $settings['private-key'] + ] ); + + $merchantPath = $braintree_config->merchantPath(); + $braintreeUrl = "https://{$environmentUrl}braintreegateway.com{$merchantPath}/{$tab}"; + } + + return $braintreeUrl; + } + + /** + * This function is callback for braintree_trial setting field. + * + * @param array $field Settings fields + * @param bool $echo Display or return + * + * @return string $html + * + * @throws \Braintree\Exception\Configuration + */ + public function settings_braintree_trial( $field, $echo = true ) { + + $braintreePlans = $this->merchant_url(); + $html = sprintf(__( 'Select your product trial form %sBraintree Plans%s', 'angelleye-gravity-forms-braintree' ),'', ''); + + if ( $echo ) { + echo $html; + } + + return $html; + } + /** * Create and display plugin settings fields. These are settings for Braintree in particular, not a feed * @@ -424,7 +765,6 @@ public function feed_settings_fields () { public function plugin_settings_fields () { return array( - array( 'title' => 'Account Settings', 'fields' => array( @@ -433,7 +773,7 @@ public function plugin_settings_fields () { 'tooltip' => 'Your Braintree Merchant ID', 'label' => 'Merchant ID', 'type' => 'text', - 'class' => 'medium' + 'class' => 'medium', ), array( 'name' => 'public-key', @@ -552,8 +892,7 @@ public function get_plugin_settings () { if( $this->settings_are_valid( $settings ) ) { return $settings; - } - else { + } else { return false; } @@ -719,4 +1058,92 @@ public function scripts() { return array_merge( parent::scripts(), $scripts ); } + + /** + * Override default billing cycles intervals for subscription plan. + * + * @return array $billing_cycles + */ + public function supported_billing_intervals() { + $billing_cycles = array( + 'month' => array( 'label' => esc_html__( 'month(s)', 'angelleye-gravity-forms-braintree' ), 'min' => 1, 'max' => 24 ) + ); + + return $billing_cycles; + } + + /** + * Get all Braintree plans using Braintree payment Gateway settings. + * + * @return array $plans + * + * @throws \Braintree\Exception\Configuration + */ + public function get_plans() { + + $gateway = $this->getBraintreeGateway(); + $plan_lists = $gateway->plan()->all(); + + $plans = array( array( + 'label' => __('Select a plan','angelleye-gravity-forms-braintree'), + 'value' => '', + )); + + if( !empty($plan_lists)) { + foreach ($plan_lists as $plan ) { + $plans[] = array( + 'label' => $plan->name, + 'value' => $plan->id, + ); + } + } + + return $plans; + } + + /** + * Get customer id using customer email address. + * + * If customer email address already exists in braintree customer lists then provide customer id, + * Otherwise create a new customer using customer details and then provide a customer id. + * + * @param array $args + * + * @return int|string $customer_id Customer id. + * + * @throws \Braintree\Exception\Configuration + */ + public function get_customer_id( $args ) { + + //check if customer detail is empty or not array then return. + if(empty($args) || !is_array($args)) { + return ''; + } + + $email = !empty($args['email']) ? $args['email'] : ''; + + $gateway = $this->getBraintreeGateway(); + + //search customer using email address + $collections = $gateway->customer()->search([ + Braintree\CustomerSearch::email()->is($email) + ]); + + $customer_id = 0; + foreach ($collections as $key => $collection) { + if( !empty($collection->id) ) { + $customer_id = $collection->id; + } + } + + //check $customer_id is empty then create a new customer. + if(empty($customer_id)) { + $customer = $gateway->customer()->create( $args ); + if(!empty($customer->customer->id)) { + $customer_id = $customer->customer->id; + } + } + + return $customer_id; + } } \ No newline at end of file diff --git a/readme.txt b/readme.txt index ec1fbe2..7a9aa51 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 -Tested up to: 5.4 -Stable tag: 3.1.2 +Tested up to: 5.6.2 +Stable tag: 4.0 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0 - 03.01.2021 = +* Feature - Added Braintree Subscription ([GFB-31](https://github.com/angelleye/gravity-forms-braintree/pull/28)) + = 3.1.2 - 05.14.2020 = * Fix - Resolved Braintree ACH/CC form validation issuw with multiple Payment Methods ([GFB-27](https://github.com/angelleye/gravity-forms-braintree/pull/28)) From c2c8956bcf661793982e43a1f3e8cbfffaaf1953 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 1 Mar 2021 15:44:37 +0530 Subject: [PATCH 83/99] Updates changeload and version for v4.0 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 7a9aa51..ad4c167 100644 --- a/readme.txt +++ b/readme.txt @@ -65,7 +65,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == = 4.0 - 03.01.2021 = -* Feature - Added Braintree Subscription ([GFB-31](https://github.com/angelleye/gravity-forms-braintree/pull/28)) +* Feature - Added Braintree Subscription ([GFB-31](https://github.com/angelleye/gravity-forms-braintree/pull/30)) = 3.1.2 - 05.14.2020 = * Fix - Resolved Braintree ACH/CC form validation issuw with multiple Payment Methods ([GFB-27](https://github.com/angelleye/gravity-forms-braintree/pull/28)) From 5fff2890093e31f718346a7766bc76a7fb639c32 Mon Sep 17 00:00:00 2001 From: Nirmal Desai Date: Tue, 16 Mar 2021 13:52:33 +0530 Subject: [PATCH 84/99] GFB-36 Adding label for Braintree CC while setting up Subscription method --- lib/class.plugify-gform-braintree.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 334ba42..281a6eb 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -680,6 +680,20 @@ public function feed_settings_fields () { //unset( $transaction_type['choices'][$index] ); //} //} + + $transactionType = ''; + foreach( $settings as $index => $setting ) { + if( !empty($setting['dependency']['field']) && $setting['dependency']['field'] == 'transactionType' ) { + $transactionType = !empty($setting['dependency']['values'][0]) ? $setting['dependency']['values'][0] :''; + } + } + + if( (!empty($_POST['_gaddon_setting_transactionType']) && $_POST['_gaddon_setting_transactionType'] == 'subscription') || ( empty($_POST['_gaddon_setting_transactionType']) && !empty($transactionType) && $transactionType == 'subscription') ) { + $form_page_link = add_query_arg([ + 'id' => !empty($_REQUEST['id']) ? $_REQUEST['id'] : '', + ], menu_page_url('gf_edit_forms', false)); + $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.','angelleye-gravity-forms-braintree'), '',''); + } $settings = $this->replace_field( 'transactionType', $transaction_type, $settings ); From b0c51b5615da1c2ca21f4e5bcf05f25142366ba0 Mon Sep 17 00:00:00 2001 From: Nirmal Desai Date: Tue, 16 Mar 2021 14:05:19 +0530 Subject: [PATCH 85/99] GFB-36 Adding label for Braintree CC while setting up Subscription method --- lib/class.plugify-gform-braintree.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 334ba42..8049c62 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -681,6 +681,20 @@ public function feed_settings_fields () { //} //} + $transactionType = ''; + foreach( $settings as $index => $setting ) { + if( !empty($setting['dependency']['field']) && $setting['dependency']['field'] == 'transactionType' ) { + $transactionType = !empty($setting['dependency']['values'][0]) ? $setting['dependency']['values'][0] :''; + } + } + + if( (!empty($_POST['_gaddon_setting_transactionType']) && $_POST['_gaddon_setting_transactionType'] == 'subscription') || ( empty($_POST['_gaddon_setting_transactionType']) && !empty($transactionType) && $transactionType == 'subscription') ) { + $form_page_link = add_query_arg([ + 'id' => !empty($_REQUEST['id']) ? $_REQUEST['id'] : '', + ], menu_page_url('gf_edit_forms', false)); + $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.','angelleye-gravity-forms-braintree'), '',''); + } + $settings = $this->replace_field( 'transactionType', $transaction_type, $settings ); $settings = parent::remove_field( 'trial', $settings ); From a8ff5d8f7e444deda51558ca9c6d8f4d4699b95b Mon Sep 17 00:00:00 2001 From: Nirmal Desai Date: Tue, 16 Mar 2021 14:19:22 +0530 Subject: [PATCH 86/99] Removed duplicate code --- lib/class.plugify-gform-braintree.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index aa0b68b..281a6eb 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -695,20 +695,6 @@ public function feed_settings_fields () { $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.','angelleye-gravity-forms-braintree'), '',''); } - $transactionType = ''; - foreach( $settings as $index => $setting ) { - if( !empty($setting['dependency']['field']) && $setting['dependency']['field'] == 'transactionType' ) { - $transactionType = !empty($setting['dependency']['values'][0]) ? $setting['dependency']['values'][0] :''; - } - } - - if( (!empty($_POST['_gaddon_setting_transactionType']) && $_POST['_gaddon_setting_transactionType'] == 'subscription') || ( empty($_POST['_gaddon_setting_transactionType']) && !empty($transactionType) && $transactionType == 'subscription') ) { - $form_page_link = add_query_arg([ - 'id' => !empty($_REQUEST['id']) ? $_REQUEST['id'] : '', - ], menu_page_url('gf_edit_forms', false)); - $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.','angelleye-gravity-forms-braintree'), '',''); - } - $settings = $this->replace_field( 'transactionType', $transaction_type, $settings ); $settings = parent::remove_field( 'trial', $settings ); From 84d8f3e6f96336ddf3857cf9fbda819ad3bd23a2 Mon Sep 17 00:00:00 2001 From: Nirmal Desai Date: Tue, 16 Mar 2021 14:26:09 +0530 Subject: [PATCH 87/99] Updates changelog and version for v4.0.1 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 5fb0d23..1ae52f1 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0 + * Version: 4.0.1 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0'; + public static $version = '4.0.1'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 281a6eb..ccc42af 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0'; + protected $_version = '4.0.1'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index ad4c167..c7741a9 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 Tested up to: 5.6.2 -Stable tag: 4.0 +Stable tag: 4.0.1 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.1 - 03.16.2021 = +* Tweak - Adding label for Braintree CC while setting up Subscription method ([GFB-36](https://github.com/angelleye/gravity-forms-braintree/pull/31)) + = 4.0 - 03.01.2021 = * Feature - Added Braintree Subscription ([GFB-31](https://github.com/angelleye/gravity-forms-braintree/pull/30)) From c54800dd3eb5347dc14ba955ecbb25aabbdab06e Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 25 Jun 2021 11:05:12 +0530 Subject: [PATCH 88/99] Braintree SDK Update, GFB-37 --- lib/Braintree.php | 22 +- lib/Braintree/AccountUpdaterDailyReport.php | 7 +- lib/Braintree/AchMandate.php | 4 +- lib/Braintree/AddOn.php | 1 + lib/Braintree/AddOnGateway.php | 1 + lib/Braintree/Address.php | 5 +- lib/Braintree/AddressGateway.php | 22 +- lib/Braintree/AmexExpressCheckoutCard.php | 79 ----- lib/Braintree/ApplePayCard.php | 3 +- lib/Braintree/ApplePayGateway.php | 23 +- lib/Braintree/ApplePayOptions.php | 1 + lib/Braintree/AuthorizationAdjustment.php | 3 +- lib/Braintree/Base.php | 31 +- lib/Braintree/BinData.php | 6 +- lib/Braintree/ClientToken.php | 3 +- lib/Braintree/ClientTokenGateway.php | 4 +- lib/Braintree/Collection.php | 14 +- lib/Braintree/Configuration.php | 190 +++++++----- .../ConnectedMerchantPayPalStatusChanged.php | 1 + .../ConnectedMerchantStatusTransitioned.php | 1 + lib/Braintree/CredentialsParser.php | 14 +- lib/Braintree/CreditCard.php | 14 +- lib/Braintree/CreditCardGateway.php | 67 +++- lib/Braintree/CreditCardVerification.php | 4 +- .../CreditCardVerificationGateway.php | 8 +- .../CreditCardVerificationSearch.php | 41 ++- lib/Braintree/Customer.php | 80 ++--- lib/Braintree/CustomerGateway.php | 86 +++--- lib/Braintree/CustomerSearch.php | 121 ++++++-- lib/Braintree/Descriptor.php | 1 + lib/Braintree/Digest.php | 7 +- lib/Braintree/Disbursement.php | 10 +- lib/Braintree/DisbursementDetails.php | 4 +- lib/Braintree/Discount.php | 1 + lib/Braintree/DiscountGateway.php | 1 + lib/Braintree/Dispute.php | 47 ++- lib/Braintree/Dispute/EvidenceDetails.php | 1 + .../Dispute/PayPalMessageDetails.php | 18 ++ .../Dispute/StatusHistoryDetails.php | 1 + lib/Braintree/Dispute/TransactionDetails.php | 9 + lib/Braintree/DisputeGateway.php | 9 +- lib/Braintree/DisputeSearch.php | 9 +- lib/Braintree/DocumentUpload.php | 6 +- lib/Braintree/DocumentUploadGateway.php | 1 + lib/Braintree/EndsWithNode.php | 1 + lib/Braintree/EqualityNode.php | 3 +- lib/Braintree/Error/Codes.php | 126 +++++--- lib/Braintree/Error/ErrorCollection.php | 11 +- lib/Braintree/Error/Validation.php | 8 +- .../Error/ValidationErrorCollection.php | 30 +- lib/Braintree/Exception.php | 1 + lib/Braintree/Exception/Authentication.php | 1 + lib/Braintree/Exception/Authorization.php | 1 + lib/Braintree/Exception/Configuration.php | 1 + lib/Braintree/Exception/Connection.php | 1 + lib/Braintree/Exception/GatewayTimeout.php | 1 + lib/Braintree/Exception/InvalidChallenge.php | 1 + lib/Braintree/Exception/InvalidSignature.php | 1 + lib/Braintree/Exception/NotFound.php | 1 + lib/Braintree/Exception/RequestTimeout.php | 1 + lib/Braintree/Exception/SSLCaFileNotFound.php | 1 + lib/Braintree/Exception/SSLCertificate.php | 1 + lib/Braintree/Exception/ServerError.php | 1 + .../Exception/ServiceUnavailable.php | 1 + .../TestOperationPerformedInProduction.php | 1 + lib/Braintree/Exception/Timeout.php | 1 + lib/Braintree/Exception/TooManyRequests.php | 1 + lib/Braintree/Exception/Unexpected.php | 1 + lib/Braintree/Exception/UpgradeRequired.php | 1 + lib/Braintree/Exception/ValidationsFailed.php | 1 + lib/Braintree/FacilitatedDetails.php | 5 +- lib/Braintree/FacilitatorDetails.php | 5 +- lib/Braintree/Gateway.php | 1 + .../{AndroidPayCard.php => GooglePayCard.php} | 21 +- .../GrantedPaymentInstrumentUpdate.php | 5 +- lib/Braintree/GraphQL.php | 4 +- lib/Braintree/GraphQLClient.php | 3 +- lib/Braintree/Http.php | 183 +---------- lib/Braintree/HttpHelpers/Curl.php | 182 +++++++++++ lib/Braintree/HttpHelpers/CurlRequest.php | 43 +++ lib/Braintree/HttpHelpers/HttpRequest.php | 13 + lib/Braintree/Instance.php | 36 ++- lib/Braintree/IsNode.php | 1 + lib/Braintree/KeyValueNode.php | 3 +- lib/Braintree/LocalPaymentCompleted.php | 12 +- lib/Braintree/LocalPaymentReversed.php | 64 ++++ lib/Braintree/MasterpassCard.php | 140 --------- lib/Braintree/Merchant.php | 7 +- lib/Braintree/MerchantAccount.php | 1 + .../MerchantAccount/AddressDetails.php | 1 + .../MerchantAccount/BusinessDetails.php | 1 + .../MerchantAccount/FundingDetails.php | 1 + .../MerchantAccount/IndividualDetails.php | 1 + lib/Braintree/MerchantAccountGateway.php | 13 +- lib/Braintree/MerchantGateway.php | 5 +- lib/Braintree/Modification.php | 4 +- lib/Braintree/MultipleValueNode.php | 21 +- lib/Braintree/MultipleValueOrTextNode.php | 1 + lib/Braintree/OAuthAccessRevocation.php | 1 + lib/Braintree/OAuthCredentials.php | 3 +- lib/Braintree/OAuthGateway.php | 9 +- lib/Braintree/OAuthResult.php | 3 +- lib/Braintree/PaginatedCollection.php | 8 +- lib/Braintree/PaginatedResult.php | 1 + lib/Braintree/PartialMatchNode.php | 1 + lib/Braintree/PartnerMerchant.php | 1 + lib/Braintree/PayPalAccount.php | 5 +- lib/Braintree/PayPalAccountGateway.php | 18 +- lib/Braintree/PaymentInstrumentType.php | 4 +- lib/Braintree/PaymentMethod.php | 3 +- lib/Braintree/PaymentMethodGateway.php | 39 +-- lib/Braintree/PaymentMethodNonce.php | 11 +- lib/Braintree/PaymentMethodNonceGateway.php | 12 +- lib/Braintree/PaymentMethodParser.php | 23 +- lib/Braintree/Plan.php | 7 +- lib/Braintree/PlanGateway.php | 3 +- lib/Braintree/ProcessorResponseTypes.php | 7 +- lib/Braintree/RangeNode.php | 3 +- lib/Braintree/ResourceCollection.php | 12 +- .../Result/CreditCardVerification.php | 17 +- lib/Braintree/Result/Error.php | 97 +++--- lib/Braintree/Result/Successful.php | 45 +-- .../Result/UsBankAccountVerification.php | 9 +- .../RevokedPaymentMethodMetadata.php | 3 +- lib/Braintree/RiskData.php | 15 +- lib/Braintree/SamsungPayCard.php | 7 +- lib/Braintree/SettlementBatchSummary.php | 3 +- .../SettlementBatchSummaryGateway.php | 14 +- lib/Braintree/ShippingMethod.php | 18 ++ lib/Braintree/SignatureService.php | 2 +- lib/Braintree/Subscription.php | 18 +- lib/Braintree/Subscription/StatusDetails.php | 1 + lib/Braintree/SubscriptionGateway.php | 22 +- lib/Braintree/SubscriptionSearch.php | 1 + lib/Braintree/Test/AuthenticationIds.php | 33 +- lib/Braintree/Test/CreditCardNumbers.php | 13 +- lib/Braintree/Test/MerchantAccount.php | 3 +- lib/Braintree/Test/Nonces.php | 144 +++++---- lib/Braintree/Test/Transaction.php | 1 + lib/Braintree/Test/TransactionAmounts.php | 7 +- lib/Braintree/Test/VenmoSdk.php | 13 +- lib/Braintree/TestingGateway.php | 1 + lib/Braintree/TextNode.php | 1 + lib/Braintree/ThreeDSecureInfo.php | 22 +- lib/Braintree/Transaction.php | 134 ++++---- lib/Braintree/Transaction/AddressDetails.php | 1 + .../AmexExpressCheckoutCardDetails.php | 42 --- .../Transaction/ApplePayCardDetails.php | 1 + .../Transaction/CreditCardDetails.php | 14 +- lib/Braintree/Transaction/CustomerDetails.php | 1 + ...rdDetails.php => GooglePayCardDetails.php} | 7 +- .../Transaction/LocalPaymentDetails.php | 1 + .../Transaction/MasterpassCardDetails.php | 51 ---- lib/Braintree/Transaction/PayPalDetails.php | 4 + .../Transaction/PayPalHereDetails.php | 9 +- .../Transaction/SamsungPayCardDetails.php | 2 +- lib/Braintree/Transaction/StatusDetails.php | 1 + .../Transaction/SubscriptionDetails.php | 1 + .../Transaction/UsBankAccountDetails.php | 1 + .../Transaction/VenmoAccountDetails.php | 2 + .../Transaction/VisaCheckoutCardDetails.php | 2 +- lib/Braintree/TransactionGateway.php | 148 +++++++-- lib/Braintree/TransactionLineItem.php | 1 + lib/Braintree/TransactionLineItemGateway.php | 8 +- lib/Braintree/TransactionSearch.php | 289 ++++++++++++++---- lib/Braintree/UnknownPaymentMethod.php | 2 +- lib/Braintree/UsBankAccount.php | 3 +- lib/Braintree/UsBankAccountGateway.php | 8 +- lib/Braintree/UsBankAccountVerification.php | 3 +- .../UsBankAccountVerificationGateway.php | 4 +- .../UsBankAccountVerificationSearch.php | 25 +- lib/Braintree/Util.php | 169 +++++----- lib/Braintree/VenmoAccount.php | 3 +- lib/Braintree/Version.php | 7 +- lib/Braintree/VisaCheckoutCard.php | 10 +- lib/Braintree/WebhookNotification.php | 58 ++-- lib/Braintree/WebhookNotificationGateway.php | 4 +- lib/Braintree/WebhookTesting.php | 1 + lib/Braintree/WebhookTestingGateway.php | 103 ++++++- lib/Braintree/Xml.php | 4 +- lib/Braintree/Xml/Generator.php | 28 +- lib/Braintree/Xml/Parser.php | 107 +++---- 182 files changed, 2319 insertions(+), 1581 deletions(-) delete mode 100644 lib/Braintree/AmexExpressCheckoutCard.php create mode 100644 lib/Braintree/Dispute/PayPalMessageDetails.php rename lib/Braintree/{AndroidPayCard.php => GooglePayCard.php} (79%) create mode 100644 lib/Braintree/HttpHelpers/Curl.php create mode 100644 lib/Braintree/HttpHelpers/CurlRequest.php create mode 100644 lib/Braintree/HttpHelpers/HttpRequest.php create mode 100644 lib/Braintree/LocalPaymentReversed.php delete mode 100644 lib/Braintree/MasterpassCard.php create mode 100644 lib/Braintree/ShippingMethod.php delete mode 100644 lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php rename lib/Braintree/Transaction/{AndroidPayCardDetails.php => GooglePayCardDetails.php} (90%) delete mode 100644 lib/Braintree/Transaction/MasterpassCardDetails.php diff --git a/lib/Braintree.php b/lib/Braintree.php index 1690af9..f24f892 100644 --- a/lib/Braintree.php +++ b/lib/Braintree.php @@ -1,4 +1,5 @@ -= 7.3.0 required'); +} + +// phpcs:ignore +class Braintree +{ + public static function requireDependencies() + { + $requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl']; + foreach ($requiredExtensions as $ext) { + if (!extension_loaded($ext)) { + throw new Braintree\Exception('The Braintree library requires the ' . $ext . ' extension.'); + } + } + } +} + +Braintree::requireDependencies(); diff --git a/lib/Braintree/AccountUpdaterDailyReport.php b/lib/Braintree/AccountUpdaterDailyReport.php index d6a32a8..39cd3fd 100644 --- a/lib/Braintree/AccountUpdaterDailyReport.php +++ b/lib/Braintree/AccountUpdaterDailyReport.php @@ -1,4 +1,5 @@ $attrib; } return __CLASS__ . '[' . - Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) . ']'; } } diff --git a/lib/Braintree/AchMandate.php b/lib/Braintree/AchMandate.php index 569ba56..3b5b3e6 100644 --- a/lib/Braintree/AchMandate.php +++ b/lib/Braintree/AchMandate.php @@ -1,4 +1,5 @@ _attributes) . ']'; @@ -48,6 +49,5 @@ public static function factory($attributes) $instance = new self(); $instance->_initialize($attributes); return $instance; - } } diff --git a/lib/Braintree/AddOn.php b/lib/Braintree/AddOn.php index e98b44b..bd2d143 100644 --- a/lib/Braintree/AddOn.php +++ b/lib/Braintree/AddOn.php @@ -1,4 +1,5 @@ _attributes) . ']'; @@ -78,7 +80,6 @@ public static function factory($attributes) $instance = new self(); $instance->_initialize($attributes); return $instance; - } diff --git a/lib/Braintree/AddressGateway.php b/lib/Braintree/AddressGateway.php index dab79ed..fc5fed0 100644 --- a/lib/Braintree/AddressGateway.php +++ b/lib/Braintree/AddressGateway.php @@ -1,4 +1,5 @@ create($attribs); return Util::returnObjectOrThrowException(__CLASS__, $result); - } /** @@ -131,11 +131,10 @@ public function find($customerOrId, $addressId) return Address::factory($response['address']); } catch (Exception\NotFound $e) { throw new Exception\NotFound( - 'address for customer ' . $customerId . + 'address for customer ' . $customerId . ' with id ' . $addressId . ' not found.' ); } - } /** @@ -162,7 +161,6 @@ public function update($customerOrId, $addressId, $attributes) $response = $this->_http->put($path, ['address' => $attributes]); return $this->_verifyGatewayResponse($response); - } /** @@ -205,7 +203,6 @@ public static function createSignature() public static function updateSignature() { return self::createSignature(); - } /** @@ -218,12 +215,12 @@ private function _validateId($id = null) { if (empty($id) || trim($id) == "") { throw new InvalidArgumentException( - 'expected address id to be set' + 'expected address id to be set' ); } if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { throw new InvalidArgumentException( - $id . ' is an invalid address id.' + $id . ' is an invalid address id.' ); } } @@ -238,15 +235,14 @@ private function _validateCustomerId($id = null) { if (empty($id) || trim($id) == "") { throw new InvalidArgumentException( - 'expected customer id to be set' + 'expected customer id to be set' ); } if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { throw new InvalidArgumentException( - $id . ' is an invalid customer id.' + $id . ' is an invalid customer id.' ); } - } /** @@ -260,7 +256,6 @@ private function _determineCustomerId($customerOrId) $customerId = ($customerOrId instanceof Customer) ? $customerOrId->id : $customerOrId; $this->_validateCustomerId($customerId); return $customerId; - } /* private class methods */ @@ -299,13 +294,12 @@ private function _verifyGatewayResponse($response) return new Result\Successful( Address::factory($response['address']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected address or apiErrorResponse" + "Expected address or apiErrorResponse" ); } - } } diff --git a/lib/Braintree/AmexExpressCheckoutCard.php b/lib/Braintree/AmexExpressCheckoutCard.php deleted file mode 100644 index 4ddc55b..0000000 --- a/lib/Braintree/AmexExpressCheckoutCard.php +++ /dev/null @@ -1,79 +0,0 @@ -== More information == - * - * See {@link https://developers.braintreepayments.com/javascript+php}
- * - * @package Braintree - * @category Resources - * - * @property-read string $bin - * @property-read string $cardMemberExpiryDate - * @property-read string $cardMemberNumber - * @property-read string $cardType - * @property-read \DateTime $createdAt - * @property-read string $customerId - * @property-read boolean $default - * @property-read string $expirationMonth - * @property-read string $expirationYear - * @property-read string $imageUrl - * @property-read string $token - * @property-read string $sourceDescription - * @property-read \Braintree\Subscription[] $subscriptions - * @property-read \DateTime $updatedAt - */ -class AmexExpressCheckoutCard extends Base -{ - /* instance methods */ - /** - * returns false if default is null or false - * - * @return boolean - */ - public function isDefault() - { - return $this->default; - } - - /** - * factory method: returns an instance of AmexExpressCheckoutCard - * to the requesting method, with populated properties - * - * @ignore - * @return AmexExpressCheckoutCard - */ - public static function factory($attributes) - { - - $instance = new self(); - $instance->_initialize($attributes); - return $instance; - } - - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $amexExpressCheckoutCardAttribs array of Amex Express Checkout card properties - * @return void - */ - protected function _initialize($amexExpressCheckoutCardAttribs) - { - // set the attributes - $this->_attributes = $amexExpressCheckoutCardAttribs; - - $subscriptionArray = []; - if (isset($amexExpressCheckoutCardAttribs['subscriptions'])) { - foreach ($amexExpressCheckoutCardAttribs['subscriptions'] AS $subscription) { - $subscriptionArray[] = Subscription::factory($subscription); - } - } - - $this->_set('subscriptions', $subscriptionArray); - } -} diff --git a/lib/Braintree/ApplePayCard.php b/lib/Braintree/ApplePayCard.php index 715cd66..d8f5128 100644 --- a/lib/Braintree/ApplePayCard.php +++ b/lib/Braintree/ApplePayCard.php @@ -1,4 +1,5 @@ _config->merchantPath() . '/processing/apple_pay/validate_domains'; $response = $this->_http->post($path, ['url' => $domain]); - if (array_key_exists('response', $response) && $response['response']['success']) - { - return new Result\Successful; - } - else if (array_key_exists('apiErrorResponse', $response)) - { + if (array_key_exists('response', $response) && $response['response']['success']) { + return new Result\Successful(); + } elseif (array_key_exists('apiErrorResponse', $response)) { return new Result\Error($response['apiErrorResponse']); } } @@ -40,24 +38,19 @@ public function unregisterDomain($domain) { $path = $this->_config->merchantPath() . '/processing/apple_pay/unregister_domain'; $this->_http->delete($path, ['url' => $domain]); - return new Result\Successful; + return new Result\Successful(); } public function registeredDomains() { $path = $this->_config->merchantPath() . '/processing/apple_pay/registered_domains'; $response = $this->_http->get($path); - if (array_key_exists('response', $response) && array_key_exists('domains', $response['response'])) - { + if (array_key_exists('response', $response) && array_key_exists('domains', $response['response'])) { $options = ApplePayOptions::factory($response['response']); return new Result\Successful($options, 'applePayOptions'); - } - else if (array_key_exists('apiErrorResponse', $response)) - { + } elseif (array_key_exists('apiErrorResponse', $response)) { return new Result\Error($response['apiErrorResponse']); - } - else - { + } else { throw new Exception\Unexpected('expected response or apiErrorResponse'); } } diff --git a/lib/Braintree/ApplePayOptions.php b/lib/Braintree/ApplePayOptions.php index 37795e7..38301d8 100644 --- a/lib/Braintree/ApplePayOptions.php +++ b/lib/Braintree/ApplePayOptions.php @@ -1,4 +1,5 @@ _attributes = $authorizationAdjustmentAttribs; } - public function __toString() + public function __toString() { return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; } diff --git a/lib/Braintree/Base.php b/lib/Braintree/Base.php index 98d9460..d1e08ad 100644 --- a/lib/Braintree/Base.php +++ b/lib/Braintree/Base.php @@ -1,4 +1,5 @@ _attributes)) { return $this->_attributes[$name]; - } - else { + } else { trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE); return null; } @@ -62,7 +62,7 @@ public function __get($name) */ public function __isset($name) { - return array_key_exists($name, $this->_attributes); + return isset($this->_attributes[$name]); } /** @@ -76,15 +76,32 @@ public function _set($key, $value) { $this->_attributes[$key] = $value; } - + /** - * Implementation of JsonSerializable - * + * Implementation of JsonSerializable + * * @ignore * @return array */ public function jsonSerialize() { - return $this->_attributes; + return $this->_attributes; + } + + /** + * Implementation of to an Array + * + * @ignore + * @return array + */ + public function toArray() + { + return array_map(function ($value) { + if (!is_array($value)) { + return method_exists($value, 'toArray') ? $value->toArray() : $value; + } else { + return $value; + } + }, $this->_attributes); } } diff --git a/lib/Braintree/BinData.php b/lib/Braintree/BinData.php index 7300f35..50802ee 100644 --- a/lib/Braintree/BinData.php +++ b/lib/Braintree/BinData.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } - } diff --git a/lib/Braintree/ClientToken.php b/lib/Braintree/ClientToken.php index 92081ef..d7dc174 100644 --- a/lib/Braintree/ClientToken.php +++ b/lib/Braintree/ClientToken.php @@ -1,4 +1,5 @@ clientToken()->generate($params); } diff --git a/lib/Braintree/ClientTokenGateway.php b/lib/Braintree/ClientTokenGateway.php index 5628516..99aa747 100644 --- a/lib/Braintree/ClientTokenGateway.php +++ b/lib/Braintree/ClientTokenGateway.php @@ -1,4 +1,5 @@ _http = new Http($gateway->config); } - public function generate($params=[]) + public function generate($params = []) { if (!array_key_exists("version", $params)) { $params["version"] = ClientToken::DEFAULT_VERSION; @@ -124,5 +125,4 @@ private function _verifyGatewayResponse($response) ); } } - } diff --git a/lib/Braintree/Collection.php b/lib/Braintree/Collection.php index 4c66b7e..bc0a4cc 100644 --- a/lib/Braintree/Collection.php +++ b/lib/Braintree/Collection.php @@ -1,4 +1,5 @@ = $this->count()) + if ($index >= $this->count()) { throw new OutOfRangeException('Index out of range'); + } $this->_collection[$index] = $value; } @@ -55,8 +57,9 @@ public function set($index, $value) */ public function remove($index) { - if($index >= $this->count()) + if ($index >= $this->count()) { throw new OutOfRangeException('Index out of range'); + } array_splice($this->_collection, $index, 1); } @@ -69,8 +72,9 @@ public function remove($index) */ public function get($index) { - if($index >= $this->count()) + if ($index >= $this->count()) { throw new OutOfRangeException('Index out of range'); + } return $this->_collection[$index]; } @@ -82,8 +86,9 @@ public function get($index) */ public function exists($index) { - if($index >= $this->count()) + if ($index >= $this->count()) { return false; + } return true; } @@ -154,5 +159,4 @@ public function offsetExists($offset) { return $this->exists($offset); } - } diff --git a/lib/Braintree/Configuration.php b/lib/Braintree/Configuration.php index a109653..351e18d 100644 --- a/lib/Braintree/Configuration.php +++ b/lib/Braintree/Configuration.php @@ -1,4 +1,5 @@ -_privateKey = $value; } + if ($kind == 'proxyHost') { + $this->_proxyHost = $value; + } + if ($kind == 'proxyPort') { + $this->_proxyPort = $value; + } + if ($kind == 'proxyType') { + $this->_proxyType = $value; + } + if ($kind == 'proxyUser') { + $this->_proxyUser = $value; + } + if ($kind == 'proxyPassword') { + $this->_proxyPassword = $value; + } if ($kind == 'timeout') { $this->_timeout = $value; } + if ($kind == 'sslVersion') { + $this->_sslVersion = $value; + } if ($kind == 'acceptGzipEncoding') { $this->_acceptGzipEncoding = $value; } } if (isset($attribs['clientId']) || isset($attribs['accessToken'])) { + // phpcs:ignore Generic.Files.LineLength if (isset($attribs['environment']) || isset($attribs['merchantId']) || isset($attribs['publicKey']) || isset($attribs['privateKey'])) { + // phpcs:ignore Generic.Files.LineLength throw new Exception\Configuration('Cannot mix OAuth credentials (clientId, clientSecret, accessToken) with key credentials (publicKey, privateKey, environment, merchantId).'); } $parsedCredentials = new CredentialsParser($attribs); @@ -88,7 +109,7 @@ public static function gateway() return new Gateway(self::$global); } - public static function environment($value=null) + public static function environment($value = null) { if (empty($value)) { return self::$global->getEnvironment(); @@ -97,7 +118,7 @@ public static function environment($value=null) self::$global->setEnvironment($value); } - public static function merchantId($value=null) + public static function merchantId($value = null) { if (empty($value)) { return self::$global->getMerchantId(); @@ -105,7 +126,7 @@ public static function merchantId($value=null) self::$global->setMerchantId($value); } - public static function publicKey($value=null) + public static function publicKey($value = null) { if (empty($value)) { return self::$global->getPublicKey(); @@ -113,7 +134,7 @@ public static function publicKey($value=null) self::$global->setPublicKey($value); } - public static function privateKey($value=null) + public static function privateKey($value = null) { if (empty($value)) { return self::$global->getPrivateKey(); @@ -127,7 +148,7 @@ public static function privateKey($value=null) * @param integer $value If provided, sets the read timeout * @return integer The read timeout used for connecting to Braintree */ - public static function timeout($value=null) + public static function timeout($value = null) { if (empty($value)) { return self::$global->getTimeout(); @@ -143,7 +164,7 @@ public static function timeout($value=null) * @param integer $value If provided, sets the SSL version * @return integer The SSL version used for connecting to Braintree */ - public static function sslVersion($value=null) + public static function sslVersion($value = null) { if (empty($value)) { return self::$global->getSslVersion(); @@ -194,18 +215,6 @@ public static function proxyType($value = null) self::$global->setProxyType($value); } - /** - * Specifies whether or not a proxy is properly configured - * - * @return bool true if a proxy is configured properly, false if not - */ - public static function isUsingProxy() - { - $proxyHost = self::$global->getProxyHost(); - $proxyPort = self::$global->getProxyPort(); - return !empty($proxyHost) && !empty($proxyPort); - } - public static function proxyUser($value = null) { if (empty($value)) { @@ -222,22 +231,10 @@ public static function proxyPassword($value = null) self::$global->setProxyPassword($value); } - /** - * Specified whether or not a username and password have been provided for - * use with an authenticated proxy - * - * @return bool true if both proxyUser and proxyPassword are present - */ - public static function isAuthenticatedProxy() - { - $proxyUser = self::$global->getProxyUser(); - $proxyPwd = self::$global->getProxyPassword(); - return !empty($proxyUser) && !empty($proxyPwd); - } - /** * Specify if the HTTP client is able to decode gzipped responses. * + * // phpcs:ignore Generic.Files.LineLength * @param bool $value If true, will send an Accept-Encoding header with a gzip value. If false, will not send an Accept-Encoding header with a gzip value. * @return bool true if an Accept-Encoding header with a gzip value will be sent, false if not */ @@ -258,12 +255,13 @@ public function assertHasAccessTokenOrKeys() { if (empty($this->_accessToken)) { if (empty($this->_merchantId)) { + // phpcs:ignore Generic.Files.LineLength throw new Exception\Configuration('Braintree\\Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree\\Gateway).'); - } else if (empty($this->_environment)) { + } elseif (empty($this->_environment)) { throw new Exception\Configuration('Braintree\\Configuration::environment needs to be set.'); - } else if (empty($this->_publicKey)) { + } elseif (empty($this->_publicKey)) { throw new Exception\Configuration('Braintree\\Configuration::publicKey needs to be set.'); - } else if (empty($this->_privateKey)) { + } elseif (empty($this->_privateKey)) { throw new Exception\Configuration('Braintree\\Configuration::privateKey needs to be set.'); } } @@ -416,7 +414,7 @@ private function setSslVersion($value) $this->_sslVersion = $value; } - private function getSslVersion() + public function getSslVersion() { return $this->_sslVersion; } @@ -464,10 +462,10 @@ public function baseUrl() * @param none * @return string Braintree GraphQL URL */ - public function graphQLBaseUrl() - { + public function graphQLBaseUrl() + { return sprintf('%s://%s:%d/graphql', $this->protocol(), $this->graphQLServerName(), $this->graphQLPortNumber()); - } + } /** * sets the merchant path based on merchant ID @@ -488,14 +486,13 @@ public function merchantPath() * @param none * @return string filepath */ - public function caFile($sslPath = NULL) + public function caFile($sslPath = null) { $sslPath = $sslPath ? $sslPath : DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'ssl' . DIRECTORY_SEPARATOR; $caPath = __DIR__ . $sslPath . 'api_braintreegateway_com.ca.crt'; - if (!file_exists($caPath)) - { + if (!file_exists($caPath)) { throw new Exception\SSLCaFileNotFound(); } @@ -532,6 +529,31 @@ public function graphQLPortNumber() return getenv("GRAPHQL_PORT") ?: 8080; } + /** + * Specifies whether or not a proxy is properly configured + * + * @return bool true if a proxy is configured properly, false if not + */ + public function isUsingProxy() + { + $proxyHost = $this->getProxyHost(); + $proxyPort = $this->getProxyPort(); + return !empty($proxyHost) && !empty($proxyPort); + } + + /** + * Specified whether or not a username and password have been provided for + * use with an authenticated proxy + * + * @return bool true if both proxyUser and proxyPassword are present + */ + public function isAuthenticatedProxy() + { + $proxyUser = $this->getProxyUser(); + $proxyPwd = $this->getProxyPassword(); + return !empty($proxyUser) && !empty($proxyPwd); + } + /** * returns http protocol depending on environment * @@ -553,21 +575,21 @@ public function protocol() */ public function serverName() { - switch($this->_environment) { - case 'production': - $serverName = 'api.braintreegateway.com'; - break; - case 'qa': - $serverName = 'gateway.qa.braintreepayments.com'; - break; - case 'sandbox': - $serverName = 'api.sandbox.braintreegateway.com'; - break; - case 'development': - case 'integration': - default: - $serverName = 'localhost'; - break; + switch ($this->_environment) { + case 'production': + $serverName = 'api.braintreegateway.com'; + break; + case 'qa': + $serverName = 'gateway.qa.braintreepayments.com'; + break; + case 'sandbox': + $serverName = 'api.sandbox.braintreegateway.com'; + break; + case 'development': + case 'integration': + default: + $serverName = 'localhost'; + break; } return $serverName; @@ -582,21 +604,21 @@ public function serverName() */ public function graphQLServerName() { - switch($this->_environment) { - case 'production': - $graphQLServerName = 'payments.braintree-api.com'; - break; - case 'qa': - $graphQLServerName = 'payments-qa.dev.braintree-api.com'; - break; - case 'sandbox': - $graphQLServerName = 'payments.sandbox.braintree-api.com'; - break; - case 'development': - case 'integration': - default: - $graphQLServerName = 'graphql.bt.local'; - break; + switch ($this->_environment) { + case 'production': + $graphQLServerName = 'payments.braintree-api.com'; + break; + case 'qa': + $graphQLServerName = 'payments-qa.dev.braintree-api.com'; + break; + case 'sandbox': + $graphQLServerName = 'payments.sandbox.braintree-api.com'; + break; + case 'development': + case 'integration': + default: + $graphQLServerName = 'graphql.bt.local'; + break; } return $graphQLServerName; @@ -612,20 +634,20 @@ public function graphQLServerName() */ public function sslOn() { - switch($this->_environment) { - case 'integration': - case 'development': - $ssl = false; - break; - case 'production': - case 'qa': - case 'sandbox': - default: - $ssl = true; - break; + switch ($this->_environment) { + case 'integration': + case 'development': + $ssl = false; + break; + case 'production': + case 'qa': + case 'sandbox': + default: + $ssl = true; + break; } - return $ssl; + return $ssl; } /** diff --git a/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php index 2d6c9a6..6175049 100644 --- a/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php +++ b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php @@ -1,4 +1,5 @@ _parseClientCredential('clientId', $this->_clientId, 'client_id')]; } if (!empty($this->_clientSecret)) { + // phpcs:ignore Generic.Files.LineLength $environments[] = ['clientSecret', $this->_parseClientCredential('clientSecret', $this->_clientSecret, 'client_secret')]; } if (!empty($this->_accessToken)) { @@ -66,7 +68,8 @@ public function parse() if ($env[1] !== $checkEnv[1]) { throw new Exception\Configuration( 'Mismatched credential environments: ' . $checkEnv[0] . ' environment is ' . $checkEnv[1] . - ' and ' . $env[0] . ' environment is ' . $env[1]); + ' and ' . $env[0] . ' environment is ' . $env[1] + ); } } @@ -74,7 +77,8 @@ public function parse() $this->_environment = $checkEnv[1]; } - public static function assertValidEnvironment($environment) { + public static function assertValidEnvironment($environment) + { if (!in_array($environment, self::$_validEnvironments)) { throw new Exception\Configuration('"' . $environment . '" is not a valid environment.'); @@ -85,7 +89,8 @@ private function _parseClientCredential($credentialType, $value, $expectedValueP { $explodedCredential = explode('$', $value); if (sizeof($explodedCredential) != 3) { - throw new Exception\Configuration('Incorrect ' . $credentialType . ' format. Expected: type$environment$token'); + $message = 'Incorrect ' . $credentialType . ' format. Expected: type$environment$token'; + throw new Exception\Configuration($message); } $gotValuePrefix = $explodedCredential[0]; @@ -103,7 +108,8 @@ private function _parseAccessToken() { $accessTokenExploded = explode('$', $this->_accessToken); if (sizeof($accessTokenExploded) != 4) { - throw new Exception\Configuration('Incorrect accessToken syntax. Expected: type$environment$merchant_id$token'); + $message = 'Incorrect accessToken syntax. Expected: type$environment$merchant_id$token'; + throw new Exception\Configuration($message); } $gotValuePrefix = $accessTokenExploded[0]; diff --git a/lib/Braintree/CreditCard.php b/lib/Braintree/CreditCard.php index 6cdc3a2..54f7d34 100644 --- a/lib/Braintree/CreditCard.php +++ b/lib/Braintree/CreditCard.php @@ -1,6 +1,8 @@ _set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); $this->_set('maskedNumber', $this->bin . '******' . $this->last4); - if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { + if (isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { $verifications = $creditCardAttribs['verifications']; usort($verifications, [$this, '_compareCreatedAtOnVerifications']); @@ -183,10 +189,10 @@ public function isEqual($otherCreditCard) * ClassName[property=value, property=value] * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** diff --git a/lib/Braintree/CreditCardGateway.php b/lib/Braintree/CreditCardGateway.php index 404b4be..7f662b1 100644 --- a/lib/Braintree/CreditCardGateway.php +++ b/lib/Braintree/CreditCardGateway.php @@ -1,8 +1,10 @@ _config->merchantPath() . '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); + $start = date('mY', $startDate); + $end = date('mY', $endDate); + $query = '/payment_methods/all/expiring_ids?start=' . $start . '&end=' . $end; + $queryPath = $this->_config->merchantPath() . $query; $response = $this->_http->post($queryPath); $pager = [ 'object' => $this, @@ -96,7 +103,10 @@ public function expiringBetween($startDate, $endDate) public function fetchExpiring($startDate, $endDate, $ids) { - $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate); + $start = date('mY', $startDate); + $end = date('mY', $endDate); + $query = '/payment_methods/all/expiring?start=' . $start . '&end=' . $end; + $queryPath = $this->_config->merchantPath() . $query; $response = $this->_http->post($queryPath, ['search' => ['ids' => $ids]]); return Util::extractAttributeAsArray( @@ -125,7 +135,6 @@ public function find($token) 'credit card with token ' . $token . ' not found' ); } - } /** @@ -148,7 +157,6 @@ public function fromNonce($nonce) 'credit card with nonce ' . $nonce . ' locked, consumed or not found' ); } - } /** @@ -269,15 +277,23 @@ public function delete($token) private static function baseOptions() { - return ['makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'verificationAccountType', 'venmoSdkSession']; + return [ + 'makeDefault', + 'skipAdvancedFraudChecking', + 'venmoSdkSession', + 'verificationAccountType', + 'verificationAmount', + 'verificationMerchantAccountId', + 'verifyCard', + ]; } private static function baseSignature($options) { return [ - 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId', + 'billingAddressId', 'cardholderName', 'cvv', 'number', 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode', - 'deviceData', 'fraudMerchantId', 'paymentMethodNonce', + 'deviceData', 'paymentMethodNonce', ['options' => $options], [ 'billingAddress' => self::billingAddressSignature() @@ -309,14 +325,32 @@ public static function createSignature() $options[] = "failOnDuplicatePaymentMethod"; $signature = self::baseSignature($options); $signature[] = 'customerId'; + $signature[] = self::threeDSecurePassThruSignature(); return $signature; } + public static function threeDSecurePassThruSignature() + { + return [ + 'threeDSecurePassThru' => [ + 'eciFlag', + 'cavv', + 'xid', + 'threeDSecureVersion', + 'authenticationResponse', + 'directoryResponse', + 'cavvAlgorithm', + 'dsTransactionId', + ] + ]; + } + public static function updateSignature() { $options = self::baseOptions(); $options[] = "failOnDuplicatePaymentMethod"; $signature = self::baseSignature($options); + $signature[] = self::threeDSecurePassThruSignature(); $updateExistingBillingSignature = [ [ @@ -326,8 +360,9 @@ public static function updateSignature() ] ]; - foreach($signature AS $key => $value) { - if(is_array($value) and array_key_exists('billingAddress', $value)) { + foreach ($signature as $key => $value) { + if (is_array($value) and array_key_exists('billingAddress', $value)) { + // phpcs:ignore $signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature); } } @@ -361,14 +396,14 @@ public function _doCreate($subPath, $params) private function _validateId($identifier = null, $identifierType = "token") { if (empty($identifier)) { - throw new InvalidArgumentException( - 'expected credit card id to be set' - ); + throw new InvalidArgumentException( + 'expected credit card id to be set' + ); } if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { throw new InvalidArgumentException( - $identifier . ' is an invalid credit card ' . $identifierType . '.' - ); + $identifier . ' is an invalid credit card ' . $identifierType . '.' + ); } } @@ -405,13 +440,13 @@ private function _verifyGatewayResponse($response) if (isset($response['creditCard'])) { // return a populated instance of Address return new Result\Successful( - CreditCard::factory($response['creditCard']) + CreditCard::factory($response['creditCard']) ); } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected address or apiErrorResponse" + "Expected address or apiErrorResponse" ); } } diff --git a/lib/Braintree/CreditCardVerification.php b/lib/Braintree/CreditCardVerification.php index 5080dda..c632c9c 100644 --- a/lib/Braintree/CreditCardVerification.php +++ b/lib/Braintree/CreditCardVerification.php @@ -1,9 +1,10 @@ _http->post($this->_config->merchantPath() . "/verifications", ['verification' => $attributes]); + $queryPath = $this->_config->merchantPath() . "/verifications"; + $response = $this->_http->post($queryPath, ['verification' => $attributes]); return $this->_verifyGatewayResponse($response); } private function _verifyGatewayResponse($response) { - if(isset($response['verification'])){ + if (isset($response['verification'])) { return new Result\Successful( CreditCardVerification::factory($response['verification']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( diff --git a/lib/Braintree/CreditCardVerificationSearch.php b/lib/Braintree/CreditCardVerificationSearch.php index 70a2813..7f2ad91 100644 --- a/lib/Braintree/CreditCardVerificationSearch.php +++ b/lib/Braintree/CreditCardVerificationSearch.php @@ -1,46 +1,57 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on Customers, see {@link https://developers.braintreepayments.com/reference/response/customer/php https://developers.braintreepayments.com/reference/response/customer/php} * * @package Braintree * @category Resources * * @property-read \Braintree\Address[] $addresses - * @property-read \Braintree\AndroidPayCard[] $androidPayCards - * @property-read \Braintree\AmexExpressCheckoutCard[] $amexExpressCheckoutCards + * @property-read \Braintree\GooglePayCard[] $googlePayCards * @property-read \Braintree\ApplePayCard[] $applePayCards * @property-read string $company * @property-read \DateTime $createdAt @@ -26,7 +27,6 @@ * @property-read string $graphQLId * @property-read string $id * @property-read string $lastName - * @property-read \Braintree\MasterpassCard[] $masterpassCards * @property-read \Braintree\PaymentMethod[] $paymentMethods * @property-read \Braintree\PayPalAccount[] $paypalAccounts * @property-read string $phone @@ -196,8 +196,7 @@ protected function _initialize($customerAttribs) $addressArray = []; if (isset($customerAttribs['addresses'])) { - - foreach ($customerAttribs['addresses'] AS $address) { + foreach ($customerAttribs['addresses'] as $address) { $addressArray[] = Address::factory($address); } } @@ -205,7 +204,7 @@ protected function _initialize($customerAttribs) $creditCardArray = []; if (isset($customerAttribs['creditCards'])) { - foreach ($customerAttribs['creditCards'] AS $creditCard) { + foreach ($customerAttribs['creditCards'] as $creditCard) { $creditCardArray[] = CreditCard::factory($creditCard); } } @@ -213,7 +212,7 @@ protected function _initialize($customerAttribs) $paypalAccountArray = []; if (isset($customerAttribs['paypalAccounts'])) { - foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { + foreach ($customerAttribs['paypalAccounts'] as $paypalAccount) { $paypalAccountArray[] = PayPalAccount::factory($paypalAccount); } } @@ -221,31 +220,23 @@ protected function _initialize($customerAttribs) $applePayCardArray = []; if (isset($customerAttribs['applePayCards'])) { - foreach ($customerAttribs['applePayCards'] AS $applePayCard) { + foreach ($customerAttribs['applePayCards'] as $applePayCard) { $applePayCardArray[] = ApplePayCard::factory($applePayCard); } } $this->_set('applePayCards', $applePayCardArray); - $androidPayCardArray = []; + $googlePayCardArray = []; if (isset($customerAttribs['androidPayCards'])) { - foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) { - $androidPayCardArray[] = AndroidPayCard::factory($androidPayCard); - } - } - $this->_set('androidPayCards', $androidPayCardArray); - - $amexExpressCheckoutCardArray = []; - if (isset($customerAttribs['amexExpressCheckoutCards'])) { - foreach ($customerAttribs['amexExpressCheckoutCards'] AS $amexExpressCheckoutCard) { - $amexExpressCheckoutCardArray[] = AmexExpressCheckoutCard::factory($amexExpressCheckoutCard); + foreach ($customerAttribs['androidPayCards'] as $googlePayCard) { + $googlePayCardArray[] = GooglePayCard::factory($googlePayCard); } } - $this->_set('amexExpressCheckoutCards', $amexExpressCheckoutCardArray); + $this->_set('googlePayCards', $googlePayCardArray); $venmoAccountArray = array(); if (isset($customerAttribs['venmoAccounts'])) { - foreach ($customerAttribs['venmoAccounts'] AS $venmoAccount) { + foreach ($customerAttribs['venmoAccounts'] as $venmoAccount) { $venmoAccountArray[] = VenmoAccount::factory($venmoAccount); } } @@ -253,23 +244,15 @@ protected function _initialize($customerAttribs) $visaCheckoutCardArray = []; if (isset($customerAttribs['visaCheckoutCards'])) { - foreach ($customerAttribs['visaCheckoutCards'] AS $visaCheckoutCard) { + foreach ($customerAttribs['visaCheckoutCards'] as $visaCheckoutCard) { $visaCheckoutCardArray[] = VisaCheckoutCard::factory($visaCheckoutCard); } } $this->_set('visaCheckoutCards', $visaCheckoutCardArray); - $masterpassCardArray = []; - if (isset($customerAttribs['masterpassCards'])) { - foreach ($customerAttribs['masterpassCards'] AS $masterpassCard) { - $masterpassCardArray[] = MasterpassCard::factory($masterpassCard); - } - } - $this->_set('masterpassCards', $masterpassCardArray); - $samsungPayCardArray = []; if (isset($customerAttribs['samsungPayCards'])) { - foreach ($customerAttribs['samsungPayCards'] AS $samsungPayCard) { + foreach ($customerAttribs['samsungPayCards'] as $samsungPayCard) { $samsungPayCardArray[] = SamsungPayCard::factory($samsungPayCard); } } @@ -277,7 +260,7 @@ protected function _initialize($customerAttribs) $usBankAccountArray = array(); if (isset($customerAttribs['usBankAccounts'])) { - foreach ($customerAttribs['usBankAccounts'] AS $usBankAccount) { + foreach ($customerAttribs['usBankAccounts'] as $usBankAccount) { $usBankAccountArray[] = UsBankAccount::factory($usBankAccount); } } @@ -287,11 +270,9 @@ protected function _initialize($customerAttribs) $this->creditCards, $this->paypalAccounts, $this->applePayCards, - $this->androidPayCards, - $this->amexExpressCheckoutCards, + $this->googlePayCards, $this->venmoAccounts, $this->visaCheckoutCards, - $this->masterpassCards, $this->samsungPayCards, $this->usBankAccounts )); @@ -307,10 +288,10 @@ protected function _initialize($customerAttribs) * returns a string representation of the customer * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** @@ -348,18 +329,19 @@ public static function _defaultPaymentMethodFilter($paymentMethod) * @var array registry of customer data */ protected $_attributes = [ - 'addresses' => '', - 'company' => '', - 'creditCards' => '', - 'email' => '', - 'fax' => '', - 'firstName' => '', - 'id' => '', - 'lastName' => '', - 'phone' => '', - 'createdAt' => '', - 'updatedAt' => '', - 'website' => '', + 'addresses' => '', + 'company' => '', + 'creditCards' => '', + 'email' => '', + 'fax' => '', + 'firstName' => '', + 'id' => '', + 'lastName' => '', + 'phone' => '', + 'taxIdentifiers' => '', + 'createdAt' => '', + 'updatedAt' => '', + 'website' => '', ]; /** diff --git a/lib/Braintree/CustomerGateway.php b/lib/Braintree/CustomerGateway.php index 25d7461..ac30430 100644 --- a/lib/Braintree/CustomerGateway.php +++ b/lib/Braintree/CustomerGateway.php @@ -1,4 +1,5 @@ == More information == * + // phpcs:ignore Generic.Files.LineLength * For more detailed information on Customers, see {@link https://developers.braintreepayments.com/reference/response/customer/php https://developers.braintreepayments.com/reference/response/customer/php} * * @package Braintree @@ -111,16 +113,17 @@ public static function createSignature() { $creditCardSignature = CreditCardGateway::createSignature(); unset($creditCardSignature[array_search('customerId', $creditCardSignature)]); - $signature = [ 'id', 'company', 'email', 'fax', 'firstName', - 'lastName', 'phone', 'website', 'deviceData', - 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce', + 'lastName', 'phone', 'website', 'deviceData', 'paymentMethodNonce', ['riskData' => - ['customerBrowser', 'customerIp', 'customer_browser', 'customer_ip'] + ['customerBrowser', 'customerIp'] ], ['creditCard' => $creditCardSignature], ['customFields' => ['_anyKey_']], + ['taxIdentifiers' => + ['countryCode', 'identifier'] + ], ['options' => [ ['paypal' => [ 'payee_email', @@ -152,8 +155,8 @@ public static function updateSignature() { $creditCardSignature = CreditCardGateway::updateSignature(); - foreach($creditCardSignature AS $key => $value) { - if(is_array($value) and array_key_exists('options', $value)) { + foreach ($creditCardSignature as $key => $value) { + if (is_array($value) and array_key_exists('options', $value)) { array_push($creditCardSignature[$key]['options'], 'updateExistingToken'); } } @@ -161,9 +164,12 @@ public static function updateSignature() $signature = [ 'id', 'company', 'email', 'fax', 'firstName', 'lastName', 'phone', 'website', 'deviceData', - 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce', 'defaultPaymentMethodToken', + 'paymentMethodNonce', 'defaultPaymentMethodToken', ['creditCard' => $creditCardSignature], ['customFields' => ['_anyKey_']], + ['taxIdentifiers' => + ['countryCode', 'identifier'] + ], ['options' => [ ['paypal' => [ 'payee_email', @@ -210,7 +216,7 @@ public function find($id, $associationFilterId = null) return Customer::factory($response['customer']); } catch (Exception\NotFound $e) { throw new Exception\NotFound( - 'customer with id ' . $id . ' not found' + 'customer with id ' . $id . ' not found' ); } } @@ -227,10 +233,11 @@ public function credit($customerId, $transactionAttribs) { $this->_validateId($customerId); return Transaction::credit( - array_merge($transactionAttribs, - ['customerId' => $customerId] - ) - ); + array_merge( + $transactionAttribs, + ['customerId' => $customerId] + ) + ); } /** @@ -275,10 +282,11 @@ public function sale($customerId, $transactionAttribs) { $this->_validateId($customerId); return Transaction::sale( - array_merge($transactionAttribs, - ['customerId' => $customerId] - ) - ); + array_merge( + $transactionAttribs, + ['customerId' => $customerId] + ) + ); } /** @@ -303,6 +311,7 @@ public function saleNoValidate($customerId, $transactionAttribs) * * If query is a string, the search will be a basic search. * If query is a hash, the search will be an advanced search. + // phpcs:ignore Generic.Files.LineLength * For more detailed information and examples, see {@link https://developers.braintreepayments.com/reference/request/customer/search/php https://developers.braintreepayments.com/reference/request/customer/search/php} * * @param mixed $query search query @@ -314,7 +323,7 @@ public function search($query) $criteria = []; foreach ($query as $term) { $result = $term->toparam(); - if(is_null($result) || empty($result)) { + if (is_null($result) || empty($result)) { throw new InvalidArgumentException('Operator must be provided'); } @@ -391,8 +400,7 @@ protected function _initialize($customerAttribs) // map each address into its own object $addressArray = []; if (isset($customerAttribs['addresses'])) { - - foreach ($customerAttribs['addresses'] AS $address) { + foreach ($customerAttribs['addresses'] as $address) { $addressArray[] = Address::factory($address); } } @@ -401,7 +409,7 @@ protected function _initialize($customerAttribs) // map each creditCard into its own object $creditCardArray = []; if (isset($customerAttribs['creditCards'])) { - foreach ($customerAttribs['creditCards'] AS $creditCard) { + foreach ($customerAttribs['creditCards'] as $creditCard) { $creditCardArray[] = CreditCard::factory($creditCard); } } @@ -410,7 +418,7 @@ protected function _initialize($customerAttribs) // map each paypalAccount into its own object $paypalAccountArray = []; if (isset($customerAttribs['paypalAccounts'])) { - foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { + foreach ($customerAttribs['paypalAccounts'] as $paypalAccount) { $paypalAccountArray[] = PayPalAccount::factory($paypalAccount); } } @@ -419,32 +427,38 @@ protected function _initialize($customerAttribs) // map each applePayCard into its own object $applePayCardArray = []; if (isset($customerAttribs['applePayCards'])) { - foreach ($customerAttribs['applePayCards'] AS $applePayCard) { + foreach ($customerAttribs['applePayCards'] as $applePayCard) { $applePayCardArray[] = ApplePayCard::factory($applePayCard); } } $this->_set('applePayCards', $applePayCardArray); - // map each androidPayCard into its own object - $androidPayCardArray = []; + // map each androidPayCard from gateway response to googlePayCard objects + $googlePayCardArray = []; if (isset($customerAttribs['androidPayCards'])) { - foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) { - $androidPayCardArray[] = AndroidPayCard::factory($androidPayCard); + foreach ($customerAttribs['androidPayCards'] as $googlePayCard) { + $googlePayCardArray[] = GooglePayCard::factory($googlePayCard); } } - $this->_set('androidPayCards', $androidPayCardArray); + $this->_set('googlePayCards', $googlePayCardArray); - $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->androidPayCards)); + $paymentMethodsArray = array_merge( + $this->creditCards, + $this->paypalAccounts, + $this->applePayCards, + $this->googlePayCards + ); + $this->_set('paymentMethods', $paymentMethodsArray); } /** * returns a string representation of the customer * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** @@ -472,10 +486,11 @@ public function paymentMethods() /** * returns the customer's default payment method * - * @return CreditCard|PayPalAccount|ApplePayCard|AndroidPayCard + * @return CreditCard|PayPalAccount|ApplePayCard|GooglePayCard */ public function defaultPaymentMethod() { + // phpcs:ignore Generic.Files.LineLength $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree\\Customer::_defaultPaymentMethodFilter'); return current($defaultPaymentMethods); } @@ -528,7 +543,8 @@ public function _doCreate($subPath, $params) * @param string customer id * @throws InvalidArgumentException */ - private function _validateId($id = null) { + private function _validateId($id = null) + { if (is_null($id)) { throw new InvalidArgumentException( 'expected customer id to be set' @@ -578,13 +594,13 @@ private function _verifyGatewayResponse($response) if (isset($response['customer'])) { // return a populated instance of Customer return new Result\Successful( - Customer::factory($response['customer']) + Customer::factory($response['customer']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected customer or apiErrorResponse" + "Expected customer or apiErrorResponse" ); } } diff --git a/lib/Braintree/CustomerSearch.php b/lib/Braintree/CustomerSearch.php index 8893aec..08bdf27 100644 --- a/lib/Braintree/CustomerSearch.php +++ b/lib/Braintree/CustomerSearch.php @@ -1,33 +1,106 @@ merchantAccountDetails = $disbursementAttribs['merchantAccount']; if (isset($disbursementAttribs['merchantAccount'])) { - $this->_set('merchantAccount', + $this->_set( + 'merchantAccount', MerchantAccount::factory($disbursementAttribs['merchantAccount']) ); } @@ -37,7 +39,7 @@ public static function factory($attributes) return $instance; } - public function __toString() + public function __toString() { $display = [ 'id', 'merchantAccountDetails', 'exceptionMessage', 'amount', @@ -46,11 +48,11 @@ public function __toString() ]; $displayAttributes = []; - foreach ($display AS $attrib) { + foreach ($display as $attrib) { $displayAttributes[$attrib] = $this->$attrib; } return __CLASS__ . '[' . - Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) . ']'; } public function isDebit() diff --git a/lib/Braintree/DisbursementDetails.php b/lib/Braintree/DisbursementDetails.php index 69b656c..4befb00 100644 --- a/lib/Braintree/DisbursementDetails.php +++ b/lib/Braintree/DisbursementDetails.php @@ -1,4 +1,5 @@ disbursementDate); } } diff --git a/lib/Braintree/Discount.php b/lib/Braintree/Discount.php index f761e20..8c0d53a 100644 --- a/lib/Braintree/Discount.php +++ b/lib/Braintree/Discount.php @@ -1,4 +1,5 @@ _set('evidence', $evidenceArray); } + if (isset($disputeAttribs['paypalMessages'])) { + $paypalMessagesArray = array_map(function ($paypalMessages) { + return new Dispute\PayPalMessageDetails($paypalMessages); + }, $disputeAttribs['paypalMessages']); + $this->_set('paypalMessages', $paypalMessagesArray); + } + if (isset($disputeAttribs['statusHistory'])) { - $statusHistoryArray = array_map(function($statusHistory) { + $statusHistoryArray = array_map(function ($statusHistory) { return new Dispute\StatusHistoryDetails($statusHistory); }, $disputeAttribs['statusHistory']); $this->_set('statusHistory', $statusHistoryArray); } if (isset($disputeAttribs['transaction'])) { - $this->_set('transaction', + $this->_set( + 'transaction', new Dispute\TransactionDetails($disputeAttribs['transaction']) ); } @@ -98,7 +114,7 @@ public static function factory($attributes) return $instance; } - public function __toString() + public function __toString() { $display = [ 'amount', 'reason', 'status', @@ -106,11 +122,11 @@ public function __toString() ]; $displayAttributes = []; - foreach ($display AS $attrib) { + foreach ($display as $attrib) { $displayAttributes[$attrib] = $this->$attrib; } return __CLASS__ . '[' . - Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) . ']'; } /** @@ -138,7 +154,14 @@ public static function addFileEvidence($disputeId, $documentIdOrRequest) * Adds text evidence to a dispute, given a dispute ID and content * * @param string $id - * @param string $contentOrRequest + * // phpcs:ignore Generic.Files.LineLength + * @param string|mixed $contentOrRequest If a string, $contentOrRequest is the text-based content for the dispute evidence. + * Alternatively, the second argument can also be an array containing: + * string $content The text-based content for the dispute evidence, and + * string $category The category for this piece of evidence + * Note: (optional) string $tag parameter is deprecated, use $category instead. + * + * Example: https://developers.braintreepayments.com/reference/request/dispute/add-text-evidence/php#submitting-categorized-evidence */ public static function addTextEvidence($id, $contentOrRequest) { @@ -185,4 +208,14 @@ public static function search($query) { return Configuration::gateway()->dispute()->search($query); } + + /** @return array */ + public static function allChargebackProtectionLevelTypes() + { + return [ + Dispute::EFFORTLESS, + Dispute::STANDARD, + Dispute::NOT_PROTECTED + ]; + } } diff --git a/lib/Braintree/Dispute/EvidenceDetails.php b/lib/Braintree/Dispute/EvidenceDetails.php index 140b841..096925e 100644 --- a/lib/Braintree/Dispute/EvidenceDetails.php +++ b/lib/Braintree/Dispute/EvidenceDetails.php @@ -1,4 +1,5 @@ $pngFile * ]); * - * For more information on DocumentUploads, see https://developers.braintreepayments.com/reference/request/document_upload/create - * + * For more information on DocumentUploads, see + * https://developers.braintreepayments.com/reference/request/document_upload/create + * * @property-read string $contentType * @property-read \DateTime $expiresAt * @property-read string $id diff --git a/lib/Braintree/DocumentUploadGateway.php b/lib/Braintree/DocumentUploadGateway.php index ea17467..1bff87f 100644 --- a/lib/Braintree/DocumentUploadGateway.php +++ b/lib/Braintree/DocumentUploadGateway.php @@ -1,4 +1,5 @@ searchTerms['is_not'] = strval($value); return $this; diff --git a/lib/Braintree/Error/Codes.php b/lib/Braintree/Error/Codes.php index 391688f..81706e1 100644 --- a/lib/Braintree/Error/Codes.php +++ b/lib/Braintree/Error/Codes.php @@ -1,4 +1,5 @@ forKey(Util::delimiterToCamelCase($key)); - if (!isset($errors)) { return []; } + if (!isset($errors)) { + return []; + } } $finalKey = Util::delimiterToCamelCase(end($pieces)); return $errors->onAttribute($finalKey); @@ -107,7 +110,7 @@ public function shallowAll() * * @ignore */ - public function __get($name) + public function __get($name) { $varName = "_$name"; return isset($this->$varName) ? $this->$varName : null; @@ -117,7 +120,7 @@ public function __get($name) * * @ignore */ - public function __toString() + public function __toString() { return sprintf('%s', $this->_errors); } diff --git a/lib/Braintree/Error/Validation.php b/lib/Braintree/Error/Validation.php index 965bbb5..6dee0b7 100644 --- a/lib/Braintree/Error/Validation.php +++ b/lib/Braintree/Error/Validation.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on Validation errors, see {@link https://developers.braintreepayments.com/reference/general/validation-errors/overview/php https://developers.braintreepayments.com/reference/general/validation-errors/overview/php} * * @package Braintree @@ -28,7 +30,7 @@ class Validation * @ignore * @param array $attributes */ - public function __construct($attributes) + public function __construct($attributes) { $this->_initializeFromArray($attributes); } @@ -41,7 +43,7 @@ public function __construct($attributes) */ private function _initializeFromArray($attributes) { - foreach($attributes AS $name => $value) { + foreach ($attributes as $name => $value) { $varName = "_$name"; $this->$varName = Util::delimiterToCamelCase($value, '_'); } @@ -51,7 +53,7 @@ private function _initializeFromArray($attributes) * * @ignore */ - public function __get($name) + public function __get($name) { $varName = "_$name"; return isset($this->$varName) ? $this->$varName : null; diff --git a/lib/Braintree/Error/ValidationErrorCollection.php b/lib/Braintree/Error/ValidationErrorCollection.php index 1c433f8..d4c8bf3 100644 --- a/lib/Braintree/Error/ValidationErrorCollection.php +++ b/lib/Braintree/Error/ValidationErrorCollection.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on Validation errors, see {@link https://developers.braintreepayments.com/reference/general/validation-errors/overview/php https://developers.braintreepayments.com/reference/general/validation-errors/overview/php} * * @package Braintree @@ -24,25 +26,24 @@ class ValidationErrorCollection extends Collection /** * @ignore */ - public function __construct($data) + public function __construct($data) { - foreach($data AS $key => $errorData) + foreach ($data as $key => $errorData) { // map errors to new collections recursively if ($key == 'errors') { - foreach ($errorData AS $error) { + foreach ($errorData as $error) { $this->_errors[] = new Validation($error); } } else { $this->_nested[$key] = new ValidationErrorCollection($errorData); } - + } } public function deepAll() { $validationErrors = array_merge([], $this->_errors); - foreach($this->_nested as $nestedErrors) - { + foreach ($this->_nested as $nestedErrors) { $validationErrors = array_merge($validationErrors, $nestedErrors->deepAll()); } return $validationErrors; @@ -51,8 +52,7 @@ public function deepAll() public function deepSize() { $total = sizeof($this->_errors); - foreach($this->_nested as $_nestedErrors) - { + foreach ($this->_nested as $_nestedErrors) { $total = $total + $_nestedErrors->deepSize(); } return $total; @@ -71,10 +71,10 @@ public function forKey($key) public function onAttribute($attribute) { $matches = []; - foreach ($this->_errors AS $key => $error) { - if($error->attribute == $attribute) { - $matches[] = $error; - } + foreach ($this->_errors as $key => $error) { + if ($error->attribute == $attribute) { + $matches[] = $error; + } } return $matches; } @@ -89,7 +89,7 @@ public function shallowAll() * * @ignore */ - public function __get($name) + public function __get($name) { $varName = "_$name"; return isset($this->$varName) ? $this->$varName : null; @@ -106,7 +106,7 @@ public function __toString() $output[] = $this->_inspect($this->_errors); } if (!empty($this->_nested)) { - foreach ($this->_nested AS $key => $values) { + foreach ($this->_nested as $key => $values) { $output[] = $this->_inspect($this->_nested); } } @@ -120,7 +120,7 @@ private function _inspect($errors, $scope = null) { $eOutput = '[' . __CLASS__ . '/errors:['; $outputErrs = []; - foreach($errors AS $error => $errorObj) { + foreach ($errors as $error => $errorObj) { if (is_array($errorObj->error)) { $outputErrs[] = "({$errorObj->error['code']} {$errorObj->error['message']})"; } diff --git a/lib/Braintree/Exception.php b/lib/Braintree/Exception.php index 094117b..d844eaf 100644 --- a/lib/Braintree/Exception.php +++ b/lib/Braintree/Exception.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } } diff --git a/lib/Braintree/FacilitatorDetails.php b/lib/Braintree/FacilitatorDetails.php index 3783f02..86c1b60 100644 --- a/lib/Braintree/FacilitatorDetails.php +++ b/lib/Braintree/FacilitatorDetails.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } } diff --git a/lib/Braintree/Gateway.php b/lib/Braintree/Gateway.php index 990c621..d11176c 100644 --- a/lib/Braintree/Gateway.php +++ b/lib/Braintree/Gateway.php @@ -1,4 +1,5 @@ == More information == * @@ -32,7 +33,7 @@ * @property-read string $virtualCardLast4 * @property-read string $virtualCardType */ -class AndroidPayCard extends Base +class GooglePayCard extends Base { /* instance methods */ /** @@ -46,11 +47,11 @@ public function isDefault() } /** - * factory method: returns an instance of AndroidPayCard + * factory method: returns an instance of GooglePayCard * to the requesting method, with populated properties * * @ignore - * @return AndroidPayCard + * @return GooglePayCard */ public static function factory($attributes) { @@ -70,17 +71,17 @@ public static function factory($attributes) * sets instance properties from an array of values * * @access protected - * @param array $androidPayCardAttribs array of Android Pay card properties + * @param array $googlePayCardAttribs array of Google Pay card properties * @return void */ - protected function _initialize($androidPayCardAttribs) + protected function _initialize($googlePayCardAttribs) { // set the attributes - $this->_attributes = $androidPayCardAttribs; + $this->_attributes = $googlePayCardAttribs; $subscriptionArray = []; - if (isset($androidPayCardAttribs['subscriptions'])) { - foreach ($androidPayCardAttribs['subscriptions'] AS $subscription) { + if (isset($googlePayCardAttribs['subscriptions'])) { + foreach ($googlePayCardAttribs['subscriptions'] as $subscription) { $subscriptionArray[] = Subscription::factory($subscription); } } diff --git a/lib/Braintree/GrantedPaymentInstrumentUpdate.php b/lib/Braintree/GrantedPaymentInstrumentUpdate.php index 899de24..9679b6b 100644 --- a/lib/Braintree/GrantedPaymentInstrumentUpdate.php +++ b/lib/Braintree/GrantedPaymentInstrumentUpdate.php @@ -1,4 +1,5 @@ == More information == * @@ -64,7 +65,7 @@ protected function _initialize($grantedPaymentInstrumentUpdateAttribs) * ClassName[property=value, property=value] * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; diff --git a/lib/Braintree/GraphQL.php b/lib/Braintree/GraphQL.php index 4ced784..68c0535 100644 --- a/lib/Braintree/GraphQL.php +++ b/lib/Braintree/GraphQL.php @@ -1,4 +1,5 @@ $definition]; if ($variables) { $graphQLRequest["variables"] = $variables; } + // phpcs:ignore Generic.Files.LineLength $response = $this->_doUrlRequest('POST', $this->_config->graphQLBaseUrl(), json_encode($graphQLRequest), null, $this->graphQLHeaders()); $result = json_decode($response["body"], true); diff --git a/lib/Braintree/GraphQLClient.php b/lib/Braintree/GraphQLClient.php index 910c7b6..5227a39 100644 --- a/lib/Braintree/GraphQLClient.php +++ b/lib/Braintree/GraphQLClient.php @@ -1,4 +1,5 @@ _service = new GraphQL($config); } - public function query($definition, $variables = Null) + public function query($definition, $variables = null) { return $this->_service->request($definition, $variables); } diff --git a/lib/Braintree/Http.php b/lib/Braintree/Http.php index a07b3b7..967aa0e 100644 --- a/lib/Braintree/Http.php +++ b/lib/Braintree/Http.php @@ -1,7 +1,9 @@ _useClientCredentials) { - return [ - 'user' => $this->_config->getClientId(), - 'password' => $this->_config->getClientSecret(), - ]; - } else if ($this->_config->isAccessToken()) { - return [ - 'token' => $this->_config->getAccessToken(), - ]; - } else { - return [ - 'user' => $this->_config->getPublicKey(), - 'password' => $this->_config->getPrivateKey(), - ]; - } - } - public function useClientCredentials() { $this->_useClientCredentials = true; @@ -120,153 +96,8 @@ private function _doRequest($httpVerb, $path, $requestBody = null, $file = null, public function _doUrlRequest($httpVerb, $url, $requestBody = null, $file = null, $customHeaders = null) { - $curl = curl_init(); - curl_setopt($curl, CURLOPT_TIMEOUT, $this->_config->timeout()); - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb); - curl_setopt($curl, CURLOPT_URL, $url); - - if ($this->_config->acceptGzipEncoding()) { - curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); - } - if ($this->_config->sslVersion()) { - curl_setopt($curl, CURLOPT_SSLVERSION, $this->_config->sslVersion()); - } - - $headers = []; - if ($customHeaders) { - $headers = $customHeaders; - } else { - $headers = $this->_getHeaders($curl); - $headers[] = 'User-Agent: Braintree PHP Library ' . Version::get(); - $headers[] = 'X-ApiVersion: ' . Configuration::API_VERSION; - $headers[] = 'Content-Type: application/xml'; - } - - $authorization = $this->_getAuthorization(); - if (isset($authorization['user'])) { - curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_setopt($curl, CURLOPT_USERPWD, $authorization['user'] . ':' . $authorization['password']); - } else if (isset($authorization['token'])) { - $headers[] = 'Authorization: Bearer ' . $authorization['token']; - } - - if ($this->_config->sslOn()) { - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); - curl_setopt($curl, CURLOPT_CAINFO, $this->getCaFile()); - } - - if (!empty($file)) { - $boundary = "---------------------" . md5(mt_rand() . microtime()); - $headers[] = "Content-Type: multipart/form-data; boundary={$boundary}"; - $this->prepareMultipart($curl, $requestBody, $file, $boundary); - } else if (!empty($requestBody)) { - curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody); - } - - if ($this->_config->isUsingProxy()) { - $proxyHost = $this->_config->getProxyHost(); - $proxyPort = $this->_config->getProxyPort(); - $proxyType = $this->_config->getProxyType(); - $proxyUser = $this->_config->getProxyUser(); - $proxyPwd= $this->_config->getProxyPassword(); - curl_setopt($curl, CURLOPT_PROXY, $proxyHost . ':' . $proxyPort); - if (!empty($proxyType)) { - curl_setopt($curl, CURLOPT_PROXYTYPE, $proxyType); - } - if ($this->_config->isAuthenticatedProxy()) { - curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPwd); - } - } - - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - $response = curl_exec($curl); - $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE); - $error_code = curl_errno($curl); - $error = curl_error($curl); - - if ($error_code == 28 && $httpStatus == 0) { - throw new Exception\Timeout(); - } - - curl_close($curl); - if ($this->_config->sslOn() && $error_code == 35) { - throw new Exception\SSLCertificate($error, $error_code); - } - - if ($error_code) { - throw new Exception\Connection($error, $error_code); - } - - return ['status' => $httpStatus, 'body' => $response]; - } - - function prepareMultipart($ch, $requestBody, $file, $boundary) { - $disallow = ["\0", "\"", "\r", "\n"]; - $fileInfo = new finfo(FILEINFO_MIME_TYPE); - $filePath = stream_get_meta_data($file)['uri']; - $data = file_get_contents($filePath); - $mimeType = $fileInfo->buffer($data); - - // build normal parameters - foreach ($requestBody as $k => $v) { - $k = str_replace($disallow, "_", $k); - $body[] = implode("\r\n", [ - "Content-Disposition: form-data; name=\"{$k}\"", - "", - filter_var($v), - ]); - } - - // build file parameter - $splitFilePath = explode(DIRECTORY_SEPARATOR, $filePath); - $filePath = end($splitFilePath); - $filePath = str_replace($disallow, "_", $filePath); - $body[] = implode("\r\n", [ - "Content-Disposition: form-data; name=\"file\"; filename=\"{$filePath}\"", - "Content-Type: {$mimeType}", - "", - $data, - ]); - - // add boundary for each parameters - array_walk($body, function (&$part) use ($boundary) { - $part = "--{$boundary}\r\n{$part}"; - }); - - // add final boundary - $body[] = "--{$boundary}--"; - $body[] = ""; - - // set options - return curl_setopt_array($ch, [ - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => implode("\r\n", $body) - ]); - } - - private function getCaFile() - { - static $memo; - - if ($memo === null) { - $caFile = $this->_config->caFile(); - - if (substr($caFile, 0, 7) !== 'phar://') { - return $caFile; - } - - $extractedCaFile = sys_get_temp_dir() . '/api_braintreegateway_com.ca.crt'; - - if (!file_exists($extractedCaFile) || sha1_file($extractedCaFile) != sha1_file($caFile)) { - if (!copy($caFile, $extractedCaFile)) { - throw new Exception\SSLCaFileNotFound(); - } - } - $memo = $extractedCaFile; - } - - return $memo; + $curlRequest = new CurlRequest($url); + // phpcs:ignore Generic.Files.LineLength + return Curl::makeRequest($httpVerb, $url, $this->_config, $curlRequest, $requestBody, $file, $customHeaders, $this->_useClientCredentials); } } diff --git a/lib/Braintree/HttpHelpers/Curl.php b/lib/Braintree/HttpHelpers/Curl.php new file mode 100644 index 0000000..a69aca6 --- /dev/null +++ b/lib/Braintree/HttpHelpers/Curl.php @@ -0,0 +1,182 @@ +setOption(CURLOPT_TIMEOUT, $config->getTimeout()); + $httpRequest->setOption(CURLOPT_CUSTOMREQUEST, $httpVerb); + $httpRequest->setOption(CURLOPT_URL, $url); + + if ($config->getAcceptGzipEncoding()) { + $httpRequest->setOption(CURLOPT_ENCODING, 'gzip'); + } + + if ($config->getSslVersion()) { + $httpRequest->setOption(CURLOPT_SSLVERSION, $config->getSslVersion()); + } + + $headers = []; + if ($customHeaders) { + $headers = $customHeaders; + } else { + $headers[] = 'Accept: application/xml'; + $headers[] = 'Content-Type: application/xml'; + $headers[] = 'User-Agent: Braintree PHP Library ' . Version::get(); + $headers[] = 'X-ApiVersion: ' . Configuration::API_VERSION; + } + + $authorization = self::_getAuthorization($config, $useClientCredentials); + if (isset($authorization['user'])) { + $httpRequest->setOption(CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + $httpRequest->setOption(CURLOPT_USERPWD, $authorization['user'] . ':' . $authorization['password']); + } elseif (isset($authorization['token'])) { + $headers[] = 'Authorization: Bearer ' . $authorization['token']; + } + + if ($config->sslOn()) { + $httpRequest->setOption(CURLOPT_SSL_VERIFYPEER, true); + $httpRequest->setOption(CURLOPT_SSL_VERIFYHOST, 2); + $httpRequest->setOption(CURLOPT_CAINFO, self::_getCaFile($config)); + } + + if (!empty($file)) { + $boundary = "---------------------" . md5(mt_rand() . microtime()); + $headers[] = "Content-Type: multipart/form-data; boundary={$boundary}"; + self::_prepareMultipart($httpRequest, $requestBody, $file, $boundary); + } elseif (!empty($requestBody)) { + $httpRequest->setOption(CURLOPT_POSTFIELDS, $requestBody); + } + + if ($config->isUsingProxy()) { + $proxyHost = $config->getProxyHost(); + $proxyPort = $config->getProxyPort(); + $proxyType = $config->getProxyType(); + $proxyUser = $config->getProxyUser(); + $proxyPwd = $config->getProxyPassword(); + $httpRequest->setOption(CURLOPT_PROXY, $proxyHost . ':' . $proxyPort); + if (!empty($proxyType)) { + $httpRequest->setOption(CURLOPT_PROXYTYPE, $proxyType); + } + if ($config->isAuthenticatedProxy()) { + $httpRequest->setOption(CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPwd); + } + } + + $httpRequest->setOption(CURLOPT_HTTPHEADER, $headers); + $httpRequest->setOption(CURLOPT_RETURNTRANSFER, true); + $response = $httpRequest->execute(); + $httpStatus = $httpRequest->getInfo(CURLINFO_HTTP_CODE); + $errorCode = $httpRequest->getErrorCode(); + $error = $httpRequest->getError(); + + if ($errorCode == 28 && $httpStatus == 0) { + throw new Exception\Timeout(); + } + + $httpRequest->close(); + if ($config->sslOn() && $errorCode == 35) { + throw new Exception\SSLCertificate($error, $errorCode); + } + + if ($errorCode) { + throw new Exception\Connection($error, $errorCode); + } + + return ['status' => $httpStatus, 'body' => $response]; + } + + private static function _getAuthorization($config, $useClientCredentials) + { + if ($useClientCredentials) { + return [ + 'user' => $config->getClientId(), + 'password' => $config->getClientSecret(), + ]; + } elseif ($config->isAccessToken()) { + return [ + 'token' => $config->getAccessToken(), + ]; + } else { + return [ + 'user' => $config->getPublicKey(), + 'password' => $config->getPrivateKey(), + ]; + } + } + + private static function _getCaFile($config) + { + static $memo; + + if ($memo === null) { + $caFile = $config->caFile(); + + if (substr($caFile, 0, 7) !== 'phar://') { + return $caFile; + } + + $extractedCaFile = sys_get_temp_dir() . '/api_braintreegateway_com.ca.crt'; + + if (!file_exists($extractedCaFile) || sha1_file($extractedCaFile) != sha1_file($caFile)) { + if (!copy($caFile, $extractedCaFile)) { + throw new Exception\SSLCaFileNotFound(); + } + } + $memo = $extractedCaFile; + } + + return $memo; + } + + private static function _prepareMultipart($httpRequest, $requestBody, $file, $boundary) + { + $disallow = ["\0", "\"", "\r", "\n"]; + $fileInfo = new finfo(FILEINFO_MIME_TYPE); + $filePath = stream_get_meta_data($file)['uri']; + $data = file_get_contents($filePath); + $mimeType = $fileInfo->buffer($data); + + // build normal parameters + foreach ($requestBody as $k => $v) { + $k = str_replace($disallow, "_", $k); + $body[] = implode("\r\n", [ + "Content-Disposition: form-data; name=\"{$k}\"", + "", + filter_var($v), + ]); + } + + // build file parameter + $splitFilePath = explode(DIRECTORY_SEPARATOR, $filePath); + $filePath = end($splitFilePath); + $filePath = str_replace($disallow, "_", $filePath); + $body[] = implode("\r\n", [ + "Content-Disposition: form-data; name=\"file\"; filename=\"{$filePath}\"", + "Content-Type: {$mimeType}", + "", + $data, + ]); + + // add boundary for each parameters + array_walk($body, function (&$part) use ($boundary) { + $part = "--{$boundary}\r\n{$part}"; + }); + + // add final boundary + $body[] = "--{$boundary}--"; + $body[] = ""; + + // set options + $httpRequest->setOption(CURLOPT_POST, true); + $httpRequest->setOption(CURLOPT_POSTFIELDS, implode("\r\n", $body)); + } +} diff --git a/lib/Braintree/HttpHelpers/CurlRequest.php b/lib/Braintree/HttpHelpers/CurlRequest.php new file mode 100644 index 0000000..11d6b6c --- /dev/null +++ b/lib/Braintree/HttpHelpers/CurlRequest.php @@ -0,0 +1,43 @@ +_handle = curl_init($url); + } + + public function setOption($name, $value) + { + curl_setopt($this->_handle, $name, $value); + } + + public function execute() + { + return curl_exec($this->_handle); + } + + public function getInfo($name) + { + return curl_getinfo($this->_handle, $name); + } + + public function getErrorCode() + { + return curl_errno($this->_handle); + } + + public function getError() + { + return curl_error($this->_handle); + } + + public function close() + { + curl_close($this->_handle); + } +} diff --git a/lib/Braintree/HttpHelpers/HttpRequest.php b/lib/Braintree/HttpHelpers/HttpRequest.php new file mode 100644 index 0000000..6329eef --- /dev/null +++ b/lib/Braintree/HttpHelpers/HttpRequest.php @@ -0,0 +1,13 @@ +_initializeFromArray($attributes); @@ -45,7 +46,7 @@ public function __get($name) */ public function __isset($name) { - return array_key_exists($name, $this->_attributes); + return isset($this->_attributes[$name]); } /** @@ -53,10 +54,10 @@ public function __isset($name) * ClassName[property=value, property=value] * @return string */ - public function __toString() + public function __toString() { $objOutput = Util::implodeAssociativeArray($this->_attributes); - return get_class($this) .'[' . $objOutput . ']'; + return get_class($this) . '[' . $objOutput . ']'; } /** * initializes instance properties from the keys/values of an array @@ -70,4 +71,31 @@ private function _initializeFromArray($attributes) $this->_attributes = $attributes; } + /** + * Implementation of JsonSerializable + * + * @ignore + * @return array + */ + public function jsonSerialize() + { + return $this->_attributes; + } + + /** + * Implementation of to an Array + * + * @ignore + * @return array + */ + public function toArray() + { + return array_map(function ($value) { + if (!is_array($value)) { + return method_exists($value, 'toArray') ? $value->toArray() : $value; + } else { + return $value; + } + }, $this->_attributes); + } } diff --git a/lib/Braintree/IsNode.php b/lib/Braintree/IsNode.php index 05583cc..90d34a5 100644 --- a/lib/Braintree/IsNode.php +++ b/lib/Braintree/IsNode.php @@ -1,4 +1,5 @@ name = $name; - $this->searchTerm = True; + $this->searchTerm = true; } public function is($value) diff --git a/lib/Braintree/LocalPaymentCompleted.php b/lib/Braintree/LocalPaymentCompleted.php index 8fd3023..80eb252 100644 --- a/lib/Braintree/LocalPaymentCompleted.php +++ b/lib/Braintree/LocalPaymentCompleted.php @@ -1,4 +1,5 @@ == More information == * @@ -25,11 +26,11 @@ class LocalPaymentCompleted extends Base { /** - * factory method: returns an instance of GrantedPaymentInstrumentUpdate + * factory method: returns an instance of LocalPaymentCompleted * to the requesting method, with populated properties * * @ignore - * @return LocalPaymentCompleted + * @return LocalPaymentCompleted */ public static function factory($attributes) { @@ -53,7 +54,8 @@ protected function _initialize($localPaymentCompletedAttribs) $this->_attributes = $localPaymentCompletedAttribs; if (isset($transactionAttribs['transaction'])) { - $this->_set('transaction', + $this->_set( + 'transaction', new Transaction( $transactionAttribs['transaction'] ) @@ -66,7 +68,7 @@ protected function _initialize($localPaymentCompletedAttribs) * ClassName[property=value, property=value] * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; diff --git a/lib/Braintree/LocalPaymentReversed.php b/lib/Braintree/LocalPaymentReversed.php new file mode 100644 index 0000000..46c2b3b --- /dev/null +++ b/lib/Braintree/LocalPaymentReversed.php @@ -0,0 +1,64 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $paymentId + */ +class LocalPaymentReversed extends Base +{ + /** + * factory method: returns an instance of LocalPaymentReversed + * to the requesting method, with populated properties + * + * @ignore + * @return LocalPaymentReversed + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->_initialize($attributes); + return $instance; + } + + /* instance methods */ + + /** + * sets instance properties from an array of values + * + * @access protected + * @param array $LocalPaymentReversedAttribs array of localPaymentReversed data + * @return void + */ + protected function _initialize($localPaymentReversedAttribs) + { + // set the attributes + $this->_attributes = $localPaymentReversedAttribs; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } +} diff --git a/lib/Braintree/MasterpassCard.php b/lib/Braintree/MasterpassCard.php deleted file mode 100644 index af6d480..0000000 --- a/lib/Braintree/MasterpassCard.php +++ /dev/null @@ -1,140 +0,0 @@ -== More information == - * - * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} - * - * @package Braintree - * @category Resources - * - * @property-read \Braintree\Address $billingAddress - * @property-read string $bin - * @property-read string $cardType - * @property-read string $cardholderName - * @property-read string $commercial - * @property-read string $countryOfIssuance - * @property-read \DateTime $createdAt - * @property-read string $customerId - * @property-read string $customerLocation - * @property-read string $debit - * @property-read boolean $default - * @property-read string $durbinRegulated - * @property-read string $expirationDate - * @property-read string $expirationMonth - * @property-read string $expirationYear - * @property-read boolean $expired - * @property-read string $healthcare - * @property-read string $imageUrl - * @property-read string $issuingBank - * @property-read string $last4 - * @property-read string $maskedNumber - * @property-read string $payroll - * @property-read string $prepaid - * @property-read string $productId - * @property-read \Braintree\Subscription[] $subscriptions - * @property-read string $token - * @property-read string $uniqueNumberIdentifier - * @property-read \DateTime $updatedAt - */ -class MasterpassCard extends Base -{ - /* instance methods */ - /** - * returns false if default is null or false - * - * @return boolean - */ - public function isDefault() - { - return $this->default; - } - - /** - * checks whether the card is expired based on the current date - * - * @return boolean - */ - public function isExpired() - { - return $this->expired; - } - - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $creditCardAttribs array of creditcard data - * @return void - */ - protected function _initialize($creditCardAttribs) - { - // set the attributes - $this->_attributes = $creditCardAttribs; - - // map each address into its own object - $billingAddress = isset($creditCardAttribs['billingAddress']) ? - Address::factory($creditCardAttribs['billingAddress']) : - null; - - $subscriptionArray = []; - if (isset($creditCardAttribs['subscriptions'])) { - foreach ($creditCardAttribs['subscriptions'] AS $subscription) { - $subscriptionArray[] = Subscription::factory($subscription); - } - } - - $this->_set('subscriptions', $subscriptionArray); - $this->_set('billingAddress', $billingAddress); - $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); - $this->_set('maskedNumber', $this->bin . '******' . $this->last4); - } - - /** - * returns false if comparing object is not a CreditCard, - * or is a CreditCard with a different id - * - * @param object $otherCreditCard customer to compare against - * @return boolean - */ - public function isEqual($otherMasterpassCard) - { - return !($otherMasterpassCard instanceof self) ? false : $this->token === $otherMasterpassCard->token; - } - - /** - * create a printable representation of the object as: - * ClassName[property=value, property=value] - * @return string - */ - public function __toString() - { - return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; - } - - /** - * factory method: returns an instance of CreditCard - * to the requesting method, with populated properties - * - * @ignore - * @return MasterpassCard - */ - public static function factory($attributes) - { - $defaultAttributes = [ - 'bin' => '', - 'expirationMonth' => '', - 'expirationYear' => '', - 'last4' => '', - ]; - - $instance = new self(); - $instance->_initialize(array_merge($defaultAttributes, $attributes)); - return $instance; - } -} diff --git a/lib/Braintree/Merchant.php b/lib/Braintree/Merchant.php index 95ba6ec..eef60f6 100644 --- a/lib/Braintree/Merchant.php +++ b/lib/Braintree/Merchant.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } } diff --git a/lib/Braintree/MerchantAccount.php b/lib/Braintree/MerchantAccount.php index 0b9c2ee..2c5e81b 100644 --- a/lib/Braintree/MerchantAccount.php +++ b/lib/Braintree/MerchantAccount.php @@ -1,4 +1,5 @@ _doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', ['merchant_account' => $attributes]); + $queryPath = '/merchant_accounts/' . $merchant_account_id . '/update_via_api'; + return $this->_doUpdate($queryPath, ['merchant_account' => $attributes]); } public static function updateSignature() @@ -47,7 +49,8 @@ public static function updateSignature() public function createForCurrency($attribs) { - $response = $this->_http->post($this->_config->merchantPath() . '/merchant_accounts/create_for_currency', ['merchant_account' => $attribs]); + $queryPath = $this->_config->merchantPath() . '/merchant_accounts/create_for_currency'; + $response = $this->_http->post($queryPath, ['merchant_account' => $attribs]); return $this->_verifyGatewayResponse($response); } @@ -133,13 +136,13 @@ private function _verifyGatewayResponse($response) if (isset($response['merchantAccount'])) { // return a populated instance of merchantAccount return new Result\Successful( - MerchantAccount::factory($response['merchantAccount']) + MerchantAccount::factory($response['merchantAccount']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected merchant account or apiErrorResponse" + "Expected merchant account or apiErrorResponse" ); } } diff --git a/lib/Braintree/MerchantGateway.php b/lib/Braintree/MerchantGateway.php index a421af8..4898bfa 100644 --- a/lib/Braintree/MerchantGateway.php +++ b/lib/Braintree/MerchantGateway.php @@ -1,4 +1,5 @@ _attributes) . ']'; } } diff --git a/lib/Braintree/MultipleValueNode.php b/lib/Braintree/MultipleValueNode.php index 7b9635f..e5e889b 100644 --- a/lib/Braintree/MultipleValueNode.php +++ b/lib/Braintree/MultipleValueNode.php @@ -1,4 +1,5 @@ name = $name; $this->items = []; - $this->allowedValues = $allowedValues; + $this->allowedValues = $allowedValues; } public function in($values) { - $bad_values = array_diff($values, $this->allowedValues); - if (count($this->allowedValues) > 0 && count($bad_values) > 0) { - $message = 'Invalid argument(s) for ' . $this->name . ':'; - foreach ($bad_values AS $bad_value) { - $message .= ' ' . $bad_value; - } - - throw new InvalidArgumentException($message); - } + $bad_values = array_diff($values, $this->allowedValues); + if (count($this->allowedValues) > 0 && count($bad_values) > 0) { + $message = 'Invalid argument(s) for ' . $this->name . ':'; + foreach ($bad_values as $bad_value) { + $message .= ' ' . $bad_value; + } + + throw new InvalidArgumentException($message); + } $this->items = $values; return $this; diff --git a/lib/Braintree/MultipleValueOrTextNode.php b/lib/Braintree/MultipleValueOrTextNode.php index 6e10c45..b8b6a21 100644 --- a/lib/Braintree/MultipleValueOrTextNode.php +++ b/lib/Braintree/MultipleValueOrTextNode.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } } diff --git a/lib/Braintree/OAuthGateway.php b/lib/Braintree/OAuthGateway.php index eaf4535..caa7b15 100644 --- a/lib/Braintree/OAuthGateway.php +++ b/lib/Braintree/OAuthGateway.php @@ -1,4 +1,5 @@ _mapSuccess($result); - } else if (isset($response['result'])) { + } elseif (isset($response['result'])) { $result = new Result\Successful( OAuthResult::factory($response['result']) ); return $this->_mapAccessTokenRevokeSuccess($result); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { $result = new Result\Error($response['apiErrorResponse']); return $this->_mapError($result); } else { @@ -77,9 +78,9 @@ public function _mapError($result) if ($error->code == Error\Codes::OAUTH_INVALID_GRANT) { $result->error = 'invalid_grant'; - } else if ($error->code == Error\Codes::OAUTH_INVALID_CREDENTIALS) { + } elseif ($error->code == Error\Codes::OAUTH_INVALID_CREDENTIALS) { $result->error = 'invalid_credentials'; - } else if ($error->code == Error\Codes::OAUTH_INVALID_SCOPE) { + } elseif ($error->code == Error\Codes::OAUTH_INVALID_SCOPE) { $result->error = 'invalid_scope'; } $result->errorDescription = explode(': ', $error->message)[1]; diff --git a/lib/Braintree/OAuthResult.php b/lib/Braintree/OAuthResult.php index cdb2ab5..6ecdd91 100644 --- a/lib/Braintree/OAuthResult.php +++ b/lib/Braintree/OAuthResult.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } } diff --git a/lib/Braintree/PaginatedCollection.php b/lib/Braintree/PaginatedCollection.php index 8382a05..4654778 100644 --- a/lib/Braintree/PaginatedCollection.php +++ b/lib/Braintree/PaginatedCollection.php @@ -1,4 +1,5 @@ _pager = $pager; $this->_pageSize = 0; @@ -84,8 +85,7 @@ public function rewind() */ public function valid() { - if ($this->_currentPage == 0 || $this->_index % $this->_pageSize == 0 && $this->_index < $this->_totalItems) - { + if ($this->_currentPage == 0 || $this->_index % $this->_pageSize == 0 && $this->_index < $this->_totalItems) { $this->_getNextPage(); } @@ -112,7 +112,7 @@ private function _getNextPage() ); } - $this->_totalItems= $result->getTotalItems(); + $this->_totalItems = $result->getTotalItems(); $this->_pageSize = $result->getPageSize(); $this->_items = $result->getCurrentPage(); } diff --git a/lib/Braintree/PaginatedResult.php b/lib/Braintree/PaginatedResult.php index 9edb046..d8f2bd1 100644 --- a/lib/Braintree/PaginatedResult.php +++ b/lib/Braintree/PaginatedResult.php @@ -1,4 +1,5 @@ _attributes) . ']'; diff --git a/lib/Braintree/PayPalAccountGateway.php b/lib/Braintree/PayPalAccountGateway.php index 3d7b2f7..231f6e3 100644 --- a/lib/Braintree/PayPalAccountGateway.php +++ b/lib/Braintree/PayPalAccountGateway.php @@ -1,4 +1,5 @@ paymentMethod()->update($token, $attribs); } - public static function delete($token, $options=[]) + public static function delete($token, $options = []) { return Configuration::gateway()->paymentMethod()->delete($token, $options); } diff --git a/lib/Braintree/PaymentMethodGateway.php b/lib/Braintree/PaymentMethodGateway.php index bca7b8d..07f1331 100644 --- a/lib/Braintree/PaymentMethodGateway.php +++ b/lib/Braintree/PaymentMethodGateway.php @@ -1,4 +1,5 @@ _doUpdate('/payment_methods/any/' . $token, ['payment_method' => $attribs]); } - public function delete($token, $options=[]) + public function delete($token, $options = []) { Util::verifyKeys(self::deleteSignature(), $options); $this->_validateId($token); @@ -78,7 +79,7 @@ public function delete($token, $options=[]) return $this->_doDelete('/payment_methods/any/' . $token . $queryString); } - public function grant($sharedPaymentMethodToken, $attribs=[]) + public function grant($sharedPaymentMethodToken, $attribs = []) { if (is_bool($attribs) === true) { $attribs = ['allow_vaulting' => $attribs]; @@ -111,11 +112,12 @@ private static function baseSignature() $optionsSignature = [ 'failOnDuplicatePaymentMethod', 'makeDefault', - 'verificationMerchantAccountId', - 'verifyCard', + 'skipAdvancedFraudChecking', + 'usBankAccountVerificationMethod', 'verificationAccountType', 'verificationAmount', - 'usBankAccountVerificationMethod', + 'verificationMerchantAccountId', + 'verifyCard', ['paypal' => [ 'payee_email', 'payeeEmail', @@ -155,6 +157,7 @@ public static function createSignature() $signature = array_merge(self::baseSignature(), [ 'customerId', 'paypalRefreshToken', + CreditCardGateway::threeDSecurePassThruSignature() ]); return $signature; } @@ -178,9 +181,7 @@ public static function updateSignature() 'xid' ]; $signature = array_merge(self::baseSignature(), [ - 'deviceSessionId', 'venmoSdkPaymentMethodCode', - 'fraudMerchantId', ['billingAddress' => $billingAddressSignature], ['threeDSecurePassThru' => $threeDSPassThruSignature] ]); @@ -272,22 +273,23 @@ private function _verifyGatewayResponse($response) { if (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); - } else if (($response)) { + } elseif (($response)) { return new Result\Successful( PaymentMethodParser::parsePaymentMethod($response), 'paymentMethod' ); } else { throw new Exception\Unexpected( - 'Expected payment method or apiErrorResponse' + 'Expected payment method or apiErrorResponse' ); } } - private function _verifyGrantResponse($response) { + private function _verifyGrantResponse($response) + { if (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); - } else if (isset($response['paymentMethodNonce'])) { + } elseif (isset($response['paymentMethodNonce'])) { return new Result\Successful( PaymentMethodNonce::factory($response['paymentMethodNonce']), 'paymentMethodNonce' @@ -299,10 +301,11 @@ private function _verifyGrantResponse($response) { } } - private function _verifyRevokeResponse($response) { + private function _verifyRevokeResponse($response) + { if (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); - } else if (isset($response['success'])) { + } elseif (isset($response['success'])) { return new Result\Successful(); } else { throw new Exception\Unexpected( @@ -321,14 +324,14 @@ private function _verifyRevokeResponse($response) { private function _validateId($identifier = null, $identifierType = 'token') { if (empty($identifier)) { - throw new InvalidArgumentException( - 'expected payment method id to be set' - ); + throw new InvalidArgumentException( + 'expected payment method id to be set' + ); } if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { throw new InvalidArgumentException( - $identifier . ' is an invalid payment method ' . $identifierType . '.' - ); + $identifier . ' is an invalid payment method ' . $identifierType . '.' + ); } } } diff --git a/lib/Braintree/PaymentMethodNonce.php b/lib/Braintree/PaymentMethodNonce.php index 832243e..a7e4200 100644 --- a/lib/Braintree/PaymentMethodNonce.php +++ b/lib/Braintree/PaymentMethodNonce.php @@ -1,4 +1,5 @@ _set('nonce', $nonceAttributes['nonce']); $this->_set('type', $nonceAttributes['type']); - if(isset($nonceAttributes['authenticationInsight'])) { + if (isset($nonceAttributes['authenticationInsight'])) { $this->_set('authenticationInsight', $nonceAttributes['authenticationInsight']); } - if(isset($nonceAttributes['binData'])) { + if (isset($nonceAttributes['binData'])) { $this->_set('binData', BinData::factory($nonceAttributes['binData'])); } - - if(isset($nonceAttributes['threeDSecureInfo'])) { + + if (isset($nonceAttributes['threeDSecureInfo'])) { $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($nonceAttributes['threeDSecureInfo'])); } } diff --git a/lib/Braintree/PaymentMethodNonceGateway.php b/lib/Braintree/PaymentMethodNonceGateway.php index 3023b7c..77482dd 100644 --- a/lib/Braintree/PaymentMethodNonceGateway.php +++ b/lib/Braintree/PaymentMethodNonceGateway.php @@ -1,4 +1,5 @@ [ 'merchantAccountId', 'authenticationInsight', - 'amount' - ] + ['authenticationInsightOptions' => [ + 'amount', + 'recurringCustomerConsent', + 'recurringMaxAmount' + ] + ]] ]]; Util::verifyKeys($schema, $params); $response = $this->_http->post($fullPath, $params); @@ -63,9 +68,8 @@ public function find($nonce) return PaymentMethodNonce::factory($response['paymentMethodNonce']); } catch (Exception\NotFound $e) { throw new Exception\NotFound( - 'payment method nonce with id ' . $nonce . ' not found' + 'payment method nonce with id ' . $nonce . ' not found' ); } - } } diff --git a/lib/Braintree/PaymentMethodParser.php b/lib/Braintree/PaymentMethodParser.php index 7175a67..bb409a5 100644 --- a/lib/Braintree/PaymentMethodParser.php +++ b/lib/Braintree/PaymentMethodParser.php @@ -1,4 +1,5 @@ _config->merchantPath() . '/plans'; $response = $this->_http->get($path); - if (key_exists('plans', $response)){ + if (key_exists('plans', $response)) { $plans = ["plan" => $response['plans']]; } else { $plans = ["plan" => []]; diff --git a/lib/Braintree/ProcessorResponseTypes.php b/lib/Braintree/ProcessorResponseTypes.php index 5bcfacc..143b2d7 100644 --- a/lib/Braintree/ProcessorResponseTypes.php +++ b/lib/Braintree/ProcessorResponseTypes.php @@ -1,4 +1,5 @@ greaterThanOrEqualTo($min)->lessThanOrEqualTo($max); + return $this->greaterThanOrEqualTo($min)->lessThanOrEqualTo($max); } public function toParam() diff --git a/lib/Braintree/ResourceCollection.php b/lib/Braintree/ResourceCollection.php index e3b05af..e1a83ff 100644 --- a/lib/Braintree/ResourceCollection.php +++ b/lib/Braintree/ResourceCollection.php @@ -1,4 +1,5 @@ _pageSize = $response["searchResults"]["pageSize"]; $this->_ids = $response["searchResults"]["ids"]; @@ -110,12 +111,9 @@ public function maximumCount() private function _getNextPage() { - if (empty($this->_ids)) - { + if (empty($this->_ids)) { $this->_items = []; - } - else - { + } else { $this->_items = $this->_getPage(array_slice($this->_ids, $this->_batchIndex, $this->_pageSize)); $this->_batchIndex += $this->_pageSize; $this->_index = 0; @@ -150,6 +148,6 @@ private function _getPage($ids) */ public function getIds() { - return $this->_ids; + return $this->_ids; } } diff --git a/lib/Braintree/Result/CreditCardVerification.php b/lib/Braintree/Result/CreditCardVerification.php index 065c1b0..cd08f32 100644 --- a/lib/Braintree/Result/CreditCardVerification.php +++ b/lib/Braintree/Result/CreditCardVerification.php @@ -1,4 +1,5 @@ _initializeFromArray($attributes); } @@ -57,21 +58,19 @@ public function __construct($attributes) */ private function _initializeFromArray($attributes) { - if(isset($attributes['riskData'])) - { + if (isset($attributes['riskData'])) { $attributes['riskData'] = RiskData::factory($attributes['riskData']); } - if(isset($attributes['globalId'])) - { + if (isset($attributes['globalId'])) { $attributes['graphQLId'] = $attributes['globalId']; } - if(isset($attributes['threeDSecureInfo'])) { + if (isset($attributes['threeDSecureInfo'])) { $attributes['threeDSecureInfo'] = ThreeDSecureInfo::factory($attributes['threeDSecureInfo']); } $this->_attributes = $attributes; - foreach($attributes AS $name => $value) { + foreach ($attributes as $name => $value) { $varName = "_$name"; $this->$varName = $value; } @@ -80,7 +79,7 @@ private function _initializeFromArray($attributes) /** * @ignore */ - public function __get($name) + public function __get($name) { $varName = "_$name"; return isset($this->$varName) ? $this->$varName : null; @@ -90,7 +89,7 @@ public function __get($name) * returns a string representation of the customer * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; diff --git a/lib/Braintree/Result/Error.php b/lib/Braintree/Result/Error.php index f1ed703..2808f07 100644 --- a/lib/Braintree/Result/Error.php +++ b/lib/Braintree/Result/Error.php @@ -1,4 +1,5 @@ params; - foreach(array_slice($pieces, 0, -1) as $key) { - $params = $params[Util::delimiterToCamelCase($key)]; - } - if ($key != 'custom_fields') { - $finalKey = Util::delimiterToCamelCase(end($pieces)); - } else { - $finalKey = end($pieces); - } - $fieldValue = isset($params[$finalKey]) ? $params[$finalKey] : null; - return $fieldValue; - } + public function valueForHtmlField($field) + { + $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY); + $params = $this->params; + foreach (array_slice($pieces, 0, -1) as $key) { + $params = $params[Util::delimiterToCamelCase($key)]; + } + if ($key != 'custom_fields') { + $finalKey = Util::delimiterToCamelCase(end($pieces)); + } else { + $finalKey = end($pieces); + } + $fieldValue = isset($params[$finalKey]) ? $params[$finalKey] : null; + return $fieldValue; + } /** * overrides default constructor * @ignore * @param array $response gateway response array */ - public function __construct($response) - { - $this->_attributes = $response; - $this->_set('errors', new ErrorCollection($response['errors'])); + public function __construct($response) + { + $this->_attributes = $response; + $this->_set('errors', new ErrorCollection($response['errors'])); - if(isset($response['verification'])) { - $this->_set('creditCardVerification', new CreditCardVerification($response['verification'])); - } else { - $this->_set('creditCardVerification', null); - } + if (isset($response['verification'])) { + $this->_set('creditCardVerification', new CreditCardVerification($response['verification'])); + } else { + $this->_set('creditCardVerification', null); + } - if(isset($response['transaction'])) { - $this->_set('transaction', Transaction::factory($response['transaction'])); - } else { - $this->_set('transaction', null); - } + if (isset($response['transaction'])) { + $this->_set('transaction', Transaction::factory($response['transaction'])); + } else { + $this->_set('transaction', null); + } - if(isset($response['subscription'])) { - $this->_set('subscription', Subscription::factory($response['subscription'])); - } else { - $this->_set('subscription', null); - } + if (isset($response['subscription'])) { + $this->_set('subscription', Subscription::factory($response['subscription'])); + } else { + $this->_set('subscription', null); + } - if(isset($response['merchantAccount'])) { - $this->_set('merchantAccount', MerchantAccount::factory($response['merchantAccount'])); - } else { - $this->_set('merchantAccount', null); - } + if (isset($response['merchantAccount'])) { + $this->_set('merchantAccount', MerchantAccount::factory($response['merchantAccount'])); + } else { + $this->_set('merchantAccount', null); + } - if(isset($response['verification'])) { - $this->_set('verification', new CreditCardVerification($response['verification'])); - } else { - $this->_set('verification', null); - } - } + if (isset($response['verification'])) { + $this->_set('verification', new CreditCardVerification($response['verification'])); + } else { + $this->_set('verification', null); + } + } /** * create a printable representation of the object as: @@ -111,12 +112,12 @@ public function __construct($response) * @ignore * @return string */ - public function __toString() + public function __toString() { $output = Util::attributesToString($this->_attributes); if (isset($this->_creditCardVerification)) { $output .= sprintf('%s', $this->_creditCardVerification); } - return __CLASS__ .'[' . $output . ']'; + return __CLASS__ . '[' . $output . ']'; } } diff --git a/lib/Braintree/Result/Successful.php b/lib/Braintree/Result/Successful.php index 68076f5..ed09102 100644 --- a/lib/Braintree/Result/Successful.php +++ b/lib/Braintree/Result/Successful.php @@ -1,4 +1,5 @@ _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn); $this->_attributes = []; $this->_returnObjectNames = []; foreach ($objects as $propertyName => $objToReturn) { - // save the name for indirect access array_push($this->_returnObjectNames, $propertyName); @@ -70,22 +74,23 @@ public function __construct($objsToReturn = [], $propertyNames = []) * @ignore * @return string string representation of the object's structure */ - public function __toString() - { - $objects = []; - foreach ($this->_returnObjectNames as $returnObjectName) { - array_push($objects, $returnObjectName); - } - return __CLASS__ . '[' . implode(', ', $objects) . ']'; - } + public function __toString() + { + $objects = []; + foreach ($this->_returnObjectNames as $returnObjectName) { + array_push($objects, $returnObjectName); + } + return __CLASS__ . '[' . implode(', ', $objects) . ']'; + } - private function _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn) { - if(count($objsToReturn) != count($propertyNames)) { - $propertyNames = []; - foreach ($objsToReturn as $obj) { - array_push($propertyNames, Util::cleanClassName(get_class($obj))); - } - } - return array_combine($propertyNames, $objsToReturn); - } + private function _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn) + { + if (count($objsToReturn) != count($propertyNames)) { + $propertyNames = []; + foreach ($objsToReturn as $obj) { + array_push($propertyNames, Util::cleanClassName(get_class($obj))); + } + } + return array_combine($propertyNames, $objsToReturn); + } } diff --git a/lib/Braintree/Result/UsBankAccountVerification.php b/lib/Braintree/Result/UsBankAccountVerification.php index cc28856..73bc9d6 100644 --- a/lib/Braintree/Result/UsBankAccountVerification.php +++ b/lib/Braintree/Result/UsBankAccountVerification.php @@ -1,4 +1,5 @@ _initializeFromArray($attributes); @@ -63,7 +64,7 @@ public function __construct($attributes) private function _initializeFromArray($attributes) { $this->_attributes = $attributes; - foreach($attributes AS $name => $value) { + foreach ($attributes as $name => $value) { $varName = "_$name"; $this->$varName = $value; } @@ -72,7 +73,7 @@ private function _initializeFromArray($attributes) /** * @ignore */ - public function __get($name) + public function __get($name) { $varName = "_$name"; return isset($this->$varName) ? $this->$varName : null; @@ -82,7 +83,7 @@ public function __get($name) * returns a string representation of the customer * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; diff --git a/lib/Braintree/RevokedPaymentMethodMetadata.php b/lib/Braintree/RevokedPaymentMethodMetadata.php index 8e5ac3e..93d67fd 100644 --- a/lib/Braintree/RevokedPaymentMethodMetadata.php +++ b/lib/Braintree/RevokedPaymentMethodMetadata.php @@ -1,4 +1,5 @@ _attributes) . ']'; diff --git a/lib/Braintree/RiskData.php b/lib/Braintree/RiskData.php index affc737..4133443 100644 --- a/lib/Braintree/RiskData.php +++ b/lib/Braintree/RiskData.php @@ -1,10 +1,16 @@ _attributes = $attributes; } + public function decisionReasons() + { + return $this->_attributes['decisionReasons']; + } + + /** * returns a string representation of the risk data * @return string @@ -28,7 +40,6 @@ protected function _initialize($attributes) public function __toString() { return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } - } diff --git a/lib/Braintree/SamsungPayCard.php b/lib/Braintree/SamsungPayCard.php index c25e0c2..e9f1185 100644 --- a/lib/Braintree/SamsungPayCard.php +++ b/lib/Braintree/SamsungPayCard.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** diff --git a/lib/Braintree/SettlementBatchSummary.php b/lib/Braintree/SettlementBatchSummary.php index f6731c7..697c0ef 100644 --- a/lib/Braintree/SettlementBatchSummary.php +++ b/lib/Braintree/SettlementBatchSummary.php @@ -1,4 +1,5 @@ settlementBatchSummary()->generate($settlement_date, $groupByCustomField); } diff --git a/lib/Braintree/SettlementBatchSummaryGateway.php b/lib/Braintree/SettlementBatchSummaryGateway.php index 61c4a75..85d0ede 100644 --- a/lib/Braintree/SettlementBatchSummaryGateway.php +++ b/lib/Braintree/SettlementBatchSummaryGateway.php @@ -1,4 +1,5 @@ $settlement_date]; - if (isset($groupByCustomField)) - { + if (isset($groupByCustomField)) { $criteria['group_by_custom_field'] = $groupByCustomField; } $params = ['settlement_batch_summary' => $criteria]; $path = $this->_config->merchantPath() . '/settlement_batch_summary'; $response = $this->_http->post($path, $params); - if (isset($groupByCustomField)) - { + if (isset($groupByCustomField)) { $response['settlementBatchSummary']['records'] = $this->_underscoreCustomField( $groupByCustomField, $response['settlementBatchSummary']['records'] @@ -71,8 +70,7 @@ private function _underscoreCustomField($groupByCustomField, $records) { $updatedRecords = []; - foreach ($records as $record) - { + foreach ($records as $record) { $camelized = Util::delimiterToCamelCase($groupByCustomField); $record[$groupByCustomField] = $record[$camelized]; unset($record[$camelized]); @@ -94,7 +92,7 @@ private function _verifyGatewayResponse($response) return new Result\Successful( SettlementBatchSummary::factory($response['settlementBatchSummary']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( diff --git a/lib/Braintree/ShippingMethod.php b/lib/Braintree/ShippingMethod.php new file mode 100644 index 0000000..682521e --- /dev/null +++ b/lib/Braintree/ShippingMethod.php @@ -0,0 +1,18 @@ +digest, $this->key, $data); } - } diff --git a/lib/Braintree/Subscription.php b/lib/Braintree/Subscription.php index 6aa28bd..34331e9 100644 --- a/lib/Braintree/Subscription.php +++ b/lib/Braintree/Subscription.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} * * @package Braintree - * + * * @property-read \Braintree\Addon[] $addOns * @property-read string $balance * @property-read int $billingDayOfMonth @@ -74,7 +76,7 @@ protected function _initialize($attributes) $addOnArray = []; if (isset($attributes['addOns'])) { - foreach ($attributes['addOns'] AS $addOn) { + foreach ($attributes['addOns'] as $addOn) { $addOnArray[] = AddOn::factory($addOn); } } @@ -82,7 +84,7 @@ protected function _initialize($attributes) $discountArray = []; if (isset($attributes['discounts'])) { - foreach ($attributes['discounts'] AS $discount) { + foreach ($attributes['discounts'] as $discount) { $discountArray[] = Discount::factory($discount); } } @@ -98,7 +100,7 @@ protected function _initialize($attributes) $statusHistory = []; if (isset($attributes['statusHistory'])) { - foreach ($attributes['statusHistory'] AS $history) { + foreach ($attributes['statusHistory'] as $history) { $statusHistory[] = new Subscription\StatusDetails($history); } } @@ -106,7 +108,7 @@ protected function _initialize($attributes) $transactionArray = []; if (isset($attributes['transactions'])) { - foreach ($attributes['transactions'] AS $transaction) { + foreach ($attributes['transactions'] as $transaction) { $transactionArray[] = Transaction::factory($transaction); } } @@ -117,19 +119,19 @@ protected function _initialize($attributes) * returns a string representation of the customer * @return string */ - public function __toString() + public function __toString() { $excludedAttributes = ['statusHistory']; $displayAttributes = []; - foreach($this->_attributes as $key => $val) { + foreach ($this->_attributes as $key => $val) { if (!in_array($key, $excludedAttributes)) { $displayAttributes[$key] = $val; } } return __CLASS__ . '[' . - Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) . ']'; } diff --git a/lib/Braintree/Subscription/StatusDetails.php b/lib/Braintree/Subscription/StatusDetails.php index d6146dc..7fd430e 100644 --- a/lib/Braintree/Subscription/StatusDetails.php +++ b/lib/Braintree/Subscription/StatusDetails.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} * * @package Braintree @@ -45,7 +47,6 @@ public function find($id) } catch (Exception\NotFound $e) { throw new Exception\NotFound('subscription with id ' . $id . ' not found'); } - } public function search($query) @@ -185,16 +186,17 @@ private static function _addOnDiscountSignature() /** * @ignore */ - private function _validateId($id = null) { + private function _validateId($id = null) + { if (empty($id)) { - throw new InvalidArgumentException( - 'expected subscription id to be set' - ); + throw new InvalidArgumentException( + 'expected subscription id to be set' + ); } if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { throw new InvalidArgumentException( - $id . ' is an invalid subscription id.' - ); + $id . ' is an invalid subscription id.' + ); } } @@ -207,16 +209,16 @@ private function _verifyGatewayResponse($response) return new Result\Successful( Subscription::factory($response['subscription']) ); - } else if (isset($response['transaction'])) { + } elseif (isset($response['transaction'])) { // return a populated instance of Transaction, for subscription retryCharge return new Result\Successful( Transaction::factory($response['transaction']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected subscription, transaction, or apiErrorResponse" + "Expected subscription, transaction, or apiErrorResponse" ); } } diff --git a/lib/Braintree/SubscriptionSearch.php b/lib/Braintree/SubscriptionSearch.php index 1b272d8..98b642d 100644 --- a/lib/Braintree/SubscriptionSearch.php +++ b/lib/Braintree/SubscriptionSearch.php @@ -1,4 +1,5 @@ _attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } - } diff --git a/lib/Braintree/Transaction.php b/lib/Braintree/Transaction.php index fe829f8..cda59ea 100644 --- a/lib/Braintree/Transaction.php +++ b/lib/Braintree/Transaction.php @@ -1,6 +1,8 @@ _attributes = $transactionAttribs; if (isset($transactionAttribs['applePay'])) { - $this->_set('applePayCardDetails', + $this->_set( + 'applePayCardDetails', new Transaction\ApplePayCardDetails( $transactionAttribs['applePay'] ) ); } + // Rename androidPayCard from API responses to GooglePayCard if (isset($transactionAttribs['androidPayCard'])) { - $this->_set('androidPayCardDetails', - new Transaction\AndroidPayCardDetails( + $this->_set( + 'googlePayCardDetails', + new Transaction\GooglePayCardDetails( $transactionAttribs['androidPayCard'] ) ); } - if (isset($transactionAttribs['masterpassCard'])) { - $this->_set('masterpassCardDetails', - new Transaction\MasterpassCardDetails( - $transactionAttribs['masterpassCard'] - ) - ); - } - if (isset($transactionAttribs['visaCheckoutCard'])) { - $this->_set('visaCheckoutCardDetails', + $this->_set( + 'visaCheckoutCardDetails', new Transaction\VisaCheckoutCardDetails( $transactionAttribs['visaCheckoutCard'] ) @@ -318,23 +321,17 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['samsungPayCard'])) { - $this->_set('samsungPayCardDetails', + $this->_set( + 'samsungPayCardDetails', new Transaction\SamsungPayCardDetails( $transactionAttribs['samsungPayCard'] ) ); } - if (isset($transactionAttribs['amexExpressCheckoutCard'])) { - $this->_set('amexExpressCheckoutCardDetails', - new Transaction\AmexExpressCheckoutCardDetails( - $transactionAttribs['amexExpressCheckoutCard'] - ) - ); - } - if (isset($transactionAttribs['venmoAccount'])) { - $this->_set('venmoAccountDetails', + $this->_set( + 'venmoAccountDetails', new Transaction\VenmoAccountDetails( $transactionAttribs['venmoAccount'] ) @@ -342,7 +339,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['creditCard'])) { - $this->_set('creditCardDetails', + $this->_set( + 'creditCardDetails', new Transaction\CreditCardDetails( $transactionAttribs['creditCard'] ) @@ -350,7 +348,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['usBankAccount'])) { - $this->_set('usBankAccount', + $this->_set( + 'usBankAccount', new Transaction\UsBankAccountDetails( $transactionAttribs['usBankAccount'] ) @@ -358,7 +357,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['paypal'])) { - $this->_set('paypalDetails', + $this->_set( + 'paypalDetails', new Transaction\PayPalDetails( $transactionAttribs['paypal'] ) @@ -366,7 +366,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['paypalHere'])) { - $this->_set('paypalHereDetails', + $this->_set( + 'paypalHereDetails', new Transaction\PayPalHereDetails( $transactionAttribs['paypalHere'] ) @@ -374,7 +375,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['localPayment'])) { - $this->_set('localPaymentDetails', + $this->_set( + 'localPaymentDetails', new Transaction\LocalPaymentDetails( $transactionAttribs['localPayment'] ) @@ -382,7 +384,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['customer'])) { - $this->_set('customerDetails', + $this->_set( + 'customerDetails', new Transaction\CustomerDetails( $transactionAttribs['customer'] ) @@ -390,7 +393,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['billing'])) { - $this->_set('billingDetails', + $this->_set( + 'billingDetails', new Transaction\AddressDetails( $transactionAttribs['billing'] ) @@ -398,7 +402,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['shipping'])) { - $this->_set('shippingDetails', + $this->_set( + 'shippingDetails', new Transaction\AddressDetails( $transactionAttribs['shipping'] ) @@ -406,7 +411,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['subscription'])) { - $this->_set('subscriptionDetails', + $this->_set( + 'subscriptionDetails', new Transaction\SubscriptionDetails( $transactionAttribs['subscription'] ) @@ -414,7 +420,8 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['descriptor'])) { - $this->_set('descriptor', + $this->_set( + 'descriptor', new Descriptor( $transactionAttribs['descriptor'] ) @@ -422,14 +429,15 @@ protected function _initialize($transactionAttribs) } if (isset($transactionAttribs['disbursementDetails'])) { - $this->_set('disbursementDetails', + $this->_set( + 'disbursementDetails', new DisbursementDetails($transactionAttribs['disbursementDetails']) ); } $disputes = []; if (isset($transactionAttribs['disputes'])) { - foreach ($transactionAttribs['disputes'] AS $dispute) { + foreach ($transactionAttribs['disputes'] as $dispute) { $disputes[] = Dispute::factory($dispute); } } @@ -438,7 +446,7 @@ protected function _initialize($transactionAttribs) $statusHistory = []; if (isset($transactionAttribs['statusHistory'])) { - foreach ($transactionAttribs['statusHistory'] AS $history) { + foreach ($transactionAttribs['statusHistory'] as $history) { $statusHistory[] = new Transaction\StatusDetails($history); } } @@ -447,7 +455,7 @@ protected function _initialize($transactionAttribs) $addOnArray = []; if (isset($transactionAttribs['addOns'])) { - foreach ($transactionAttribs['addOns'] AS $addOn) { + foreach ($transactionAttribs['addOns'] as $addOn) { $addOnArray[] = AddOn::factory($addOn); } } @@ -455,7 +463,7 @@ protected function _initialize($transactionAttribs) $discountArray = []; if (isset($transactionAttribs['discounts'])) { - foreach ($transactionAttribs['discounts'] AS $discount) { + foreach ($transactionAttribs['discounts'] as $discount) { $discountArray[] = Discount::factory($discount); } } @@ -463,23 +471,23 @@ protected function _initialize($transactionAttribs) $authorizationAdjustments = []; if (isset($transactionAttribs['authorizationAdjustments'])) { - foreach ($transactionAttribs['authorizationAdjustments'] AS $authorizationAdjustment) { + foreach ($transactionAttribs['authorizationAdjustments'] as $authorizationAdjustment) { $authorizationAdjustments[] = AuthorizationAdjustment::factory($authorizationAdjustment); } } $this->_set('authorizationAdjustments', $authorizationAdjustments); - if(isset($transactionAttribs['riskData'])) { + if (isset($transactionAttribs['riskData'])) { $this->_set('riskData', RiskData::factory($transactionAttribs['riskData'])); } - if(isset($transactionAttribs['threeDSecureInfo'])) { + if (isset($transactionAttribs['threeDSecureInfo'])) { $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($transactionAttribs['threeDSecureInfo'])); } - if(isset($transactionAttribs['facilitatedDetails'])) { + if (isset($transactionAttribs['facilitatedDetails'])) { $this->_set('facilitatedDetails', FacilitatedDetails::factory($transactionAttribs['facilitatedDetails'])); } - if(isset($transactionAttribs['facilitatorDetails'])) { + if (isset($transactionAttribs['facilitatorDetails'])) { $this->_set('facilitatorDetails', FacilitatorDetails::factory($transactionAttribs['facilitatorDetails'])); } } @@ -488,7 +496,7 @@ protected function _initialize($transactionAttribs) * returns a string representation of the transaction * @return string */ - public function __toString() + public function __toString() { // array of attributes to print $display = [ @@ -497,11 +505,11 @@ public function __toString() ]; $displayAttributes = []; - foreach ($display AS $attrib) { + foreach ($display as $attrib) { $displayAttributes[$attrib] = $this->$attrib; } return __CLASS__ . '[' . - Util::attributesToString($displayAttributes) .']'; + Util::attributesToString($displayAttributes) . ']'; } public function isEqual($otherTx) @@ -514,31 +522,31 @@ public function vaultCreditCard() $token = $this->creditCardDetails->token; if (empty($token)) { return null; - } - else { + } else { return CreditCard::find($token); } } - /** @return void|Braintree\Customer */ + /** @return null|\Braintree\Customer */ public function vaultCustomer() { $customerId = $this->customerDetails->id; if (empty($customerId)) { return null; - } - else { + } else { return Customer::find($customerId); } } /** @return boolean */ - public function isDisbursed() { + public function isDisbursed() + { return $this->disbursementDetails->isValid(); } /** @return line items */ - public function lineItems() { + public function lineItems() + { return Configuration::gateway()->transactionLineItem()->findAll($this->id); } @@ -556,6 +564,17 @@ public static function factory($attributes) return $instance; } + /** + * adjustAuthorization: It is a static method to invoke + * method in the TransactionGateway + * + * @param string transactionId + * @param string amount + */ + public static function adjustAuthorization($transactionId, $amount) + { + return Configuration::gateway()->transaction()->adjustAuthorization($transactionId, $amount); + } // static methods redirecting to gateway @@ -621,6 +640,7 @@ public static function submitForSettlement($transactionId, $amount = null, $attr public static function submitForSettlementNoValidate($transactionId, $amount = null, $attribs = []) { + // phpcs:ignore Generic.Files.LineLength return Configuration::gateway()->transaction()->submitForSettlementNoValidate($transactionId, $amount, $attribs); } diff --git a/lib/Braintree/Transaction/AddressDetails.php b/lib/Braintree/Transaction/AddressDetails.php index d5770da..e59c296 100644 --- a/lib/Braintree/Transaction/AddressDetails.php +++ b/lib/Braintree/Transaction/AddressDetails.php @@ -1,4 +1,5 @@ _attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; - } } diff --git a/lib/Braintree/Transaction/CustomerDetails.php b/lib/Braintree/Transaction/CustomerDetails.php index cdfb4d9..8841fca 100644 --- a/lib/Braintree/Transaction/CustomerDetails.php +++ b/lib/Braintree/Transaction/CustomerDetails.php @@ -1,4 +1,5 @@ _attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; - $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; - - } -} diff --git a/lib/Braintree/Transaction/PayPalDetails.php b/lib/Braintree/Transaction/PayPalDetails.php index 8913b66..3d163f8 100644 --- a/lib/Braintree/Transaction/PayPalDetails.php +++ b/lib/Braintree/Transaction/PayPalDetails.php @@ -1,4 +1,5 @@ _attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; - } } diff --git a/lib/Braintree/Transaction/StatusDetails.php b/lib/Braintree/Transaction/StatusDetails.php index 6da46ae..c6df5b4 100644 --- a/lib/Braintree/Transaction/StatusDetails.php +++ b/lib/Braintree/Transaction/StatusDetails.php @@ -1,4 +1,5 @@ _attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear; $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4; - } } diff --git a/lib/Braintree/TransactionGateway.php b/lib/Braintree/TransactionGateway.php index 596146e..2ba16a2 100644 --- a/lib/Braintree/TransactionGateway.php +++ b/lib/Braintree/TransactionGateway.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on Transactions, see {@link https://developers.braintreepayments.com/reference/response/transaction/php https://developers.braintreepayments.com/reference/response/transaction/php} * * @package Braintree @@ -45,6 +47,7 @@ public function cloneTransaction($transactionId, $attribs) private function create($attribs) { Util::verifyKeys(self::createSignature(), $attribs); + $attribs = Util::replaceKey($attribs, 'googlePayCard', 'androidPayCard'); return $this->_doCreate('/transactions', ['transaction' => $attribs]); } @@ -78,12 +81,11 @@ public static function createSignature() 'channel', 'customerId', 'deviceData', - 'deviceSessionId', - 'fraudMerchantId', 'merchantAccountId', 'orderId', 'paymentMethodNonce', 'paymentMethodToken', + 'productSku', 'purchaseOrderNumber', 'recurring', 'serviceFeeAmount', @@ -100,14 +102,26 @@ public static function createSignature() 'transactionSource', 'type', 'venmoSdkPaymentMethodCode', + 'scaExemption', 'shippingAmount', 'discountAmount', 'shipsFromPostalCode', ['riskData' => - ['customerBrowser', 'customerIp', 'customer_browser', 'customer_ip'] + [ + 'customerBrowser', 'customerIp', 'customerDeviceId', + 'customerLocationZip', 'customerTenure'], ], ['creditCard' => - ['token', 'cardholderName', 'cvv', 'expirationDate', 'expirationMonth', 'expirationYear', 'number'], + [ + 'token', + 'cardholderName', + 'cvv', + 'expirationDate', + 'expirationMonth', + 'expirationYear', + 'number', + ['paymentReaderCardDetails' => ['encryptedCardData', 'keySerialNumber']], + ], ], ['customer' => [ @@ -118,15 +132,15 @@ public static function createSignature() [ 'firstName', 'lastName', 'company', 'countryName', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', - 'extendedAddress', 'locality', 'postalCode', 'region', + 'extendedAddress', 'locality', 'phoneNumber', 'postalCode', 'region', 'streetAddress'], ], ['shipping' => [ 'firstName', 'lastName', 'company', 'countryName', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric', - 'extendedAddress', 'locality', 'postalCode', 'region', - 'streetAddress'], + 'extendedAddress', 'locality', 'phoneNumber', 'postalCode', 'region', + 'shippingMethod', 'streetAddress'], ], ['threeDSecurePassThru' => [ @@ -186,7 +200,16 @@ public static function createSignature() ['customFields' => ['_anyKey_']], ['descriptor' => ['name', 'phone', 'url']], ['paypalAccount' => ['payeeId', 'payeeEmail', 'payerId', 'paymentId']], - ['applePayCard' => ['number', 'cardholderName', 'cryptogram', 'expirationMonth', 'expirationYear', 'eciIndicator']], + ['applePayCard' => + [ + 'cardholderName', + 'cryptogram', + 'eciIndicator', + 'expirationMonth', + 'expirationYear', + 'number' + ] + ], ['industry' => ['industryType', ['data' => @@ -250,10 +273,39 @@ public static function createSignature() ] ] ], - ['lineItems' => ['quantity', 'name', 'description', 'kind', 'unitAmount', 'unitTaxAmount', 'totalAmount', 'discountAmount', 'taxAmount', 'unitOfMeasure', 'productCode', 'commodityCode', 'url']], + ['lineItems' => + [ + 'commodityCode', + 'description', + 'discountAmount', + 'kind', + 'name', + 'productCode', + 'quantity', + 'taxAmount', + 'totalAmount', + 'unitAmount', + 'unitOfMeasure', + 'unitTaxAmount', + 'url' + ] + ], ['externalVault' => ['status' , 'previousNetworkTransactionId'], - ] + ], + ['googlePayCard' => + [ + 'cryptogram', + 'eciIndicator', + 'expirationMonth', + 'expirationYear', + 'googleTransactionId', + 'number', + 'sourceCardLastFour', + 'sourceCardType' + ] + ], + ['installments' => ['count']] ]; } @@ -266,7 +318,23 @@ public static function submitForSettlementSignature() 'shippingAmount', 'discountAmount', 'shipsFromPostalCode', - ['lineItems' => ['quantity', 'name', 'description', 'kind', 'unitAmount', 'unitTaxAmount', 'totalAmount', 'discountAmount', 'taxAmount', 'unitOfMeasure', 'productCode', 'commodityCode', 'url']], + ['lineItems' => + [ + 'commodityCode', + 'description', + 'discountAmount', + 'kind', + 'name', + 'productCode', + 'quantity', + 'taxAmount', + 'totalAmount', + 'unitAmount', + 'unitOfMeasure', + 'unitTaxAmount', + 'url' + ] + ], ]; } @@ -277,7 +345,11 @@ public static function updateDetailsSignature() public static function refundSignature() { - return ['amount', 'orderId']; + return [ + 'amount', + 'merchantAccountId', + 'orderId' + ]; } /** @@ -318,17 +390,20 @@ public function find($id) return Transaction::factory($response['transaction']); } catch (Exception\NotFound $e) { throw new Exception\NotFound( - 'transaction with id ' . $id . ' not found' + 'transaction with id ' . $id . ' not found' ); } } /** * new sale - * @param array $attribs + * @param array $attribs (Note: $recurring param is deprecated. Use $transactionSource instead) * @return Result\Successful|Result\Error */ public function sale($attribs) { + if (array_key_exists('recurring', $attribs)) { + trigger_error('$recurring is deprecated, use $transactionSource instead', E_USER_DEPRECATED); + } return $this->create(array_merge(['type' => Transaction::SALE], $attribs)); } @@ -350,6 +425,7 @@ public function saleNoValidate($attribs) * * If query is a string, the search will be a basic search. * If query is a hash, the search will be an advanced search. + * // phpcs:ignore Generic.Files.LineLength * For more detailed information and examples, see {@link https://developers.braintreepayments.com/reference/request/transaction/search/php https://developers.braintreepayments.com/reference/request/transaction/search/php} * * @param mixed $query search query @@ -399,6 +475,25 @@ public function fetch($query, $ids) } } + /** + * Adjusts the authorization amount of a transaction + * + * @access public + * @param string $transactionId + * @param string amount + * + * @return Result\Successful|Result\Error + * @throws Exception\Unexpected + */ + public function adjustAuthorization($transactionId, $amount) + { + self::_validateId($transactionId); + $params = ['amount' => $amount]; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/adjust_authorization'; + $response = $this->_http->put($path, ['transaction' => $params]); + return $this->_verifyGatewayResponse($response); + } + /** * void a transaction by id * @@ -409,7 +504,7 @@ public function void($transactionId) { $this->_validateId($transactionId); - $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/void'; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/void'; $response = $this->_http->put($path); return $this->_verifyGatewayResponse($response); } @@ -428,7 +523,7 @@ public function submitForSettlement($transactionId, $amount = null, $attribs = [ Util::verifyKeys(self::submitForSettlementSignature(), $attribs); $attribs['amount'] = $amount; - $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_settlement'; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/submit_for_settlement'; $response = $this->_http->put($path, ['transaction' => $attribs]); return $this->_verifyGatewayResponse($response); } @@ -444,7 +539,7 @@ public function updateDetails($transactionId, $attribs = []) $this->_validateId($transactionId); Util::verifyKeys(self::updateDetailsSignature(), $attribs); - $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/update_details'; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/update_details'; $response = $this->_http->put($path, ['transaction' => $attribs]); return $this->_verifyGatewayResponse($response); } @@ -455,7 +550,7 @@ public function submitForPartialSettlement($transactionId, $amount, $attribs = [ Util::verifyKeys(self::submitForSettlementSignature(), $attribs); $attribs['amount'] = $amount; - $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_partial_settlement'; + $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/submit_for_partial_settlement'; $response = $this->_http->post($path, ['transaction' => $attribs]); return $this->_verifyGatewayResponse($response); } @@ -491,7 +586,7 @@ public function refund($transactionId, $amount_or_options = null) { self::_validateId($transactionId); - if(gettype($amount_or_options) == "array") { + if (gettype($amount_or_options) == "array") { $options = $amount_or_options; } else { $options = [ @@ -528,11 +623,12 @@ public function _doCreate($subPath, $params) * @param string transaction id * @throws InvalidArgumentException */ - private function _validateId($id = null) { + private function _validateId($id = null) + { if (empty($id)) { - throw new InvalidArgumentException( - 'expected transaction id to be set' - ); + throw new InvalidArgumentException( + 'expected transaction id to be set' + ); } } @@ -554,13 +650,13 @@ private function _verifyGatewayResponse($response) if (isset($response['transaction'])) { // return a populated instance of Transaction return new Result\Successful( - Transaction::factory($response['transaction']) + Transaction::factory($response['transaction']) ); - } else if (isset($response['apiErrorResponse'])) { + } elseif (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); } else { throw new Exception\Unexpected( - "Expected transaction or apiErrorResponse" + "Expected transaction or apiErrorResponse" ); } } diff --git a/lib/Braintree/TransactionLineItem.php b/lib/Braintree/TransactionLineItem.php index ad4a04b..fa392f2 100644 --- a/lib/Braintree/TransactionLineItem.php +++ b/lib/Braintree/TransactionLineItem.php @@ -1,4 +1,5 @@ imageUrl = 'https://assets.braintreegateway.com/payment_method_logo/unknown.png'; $this->_attributes = $unknownPaymentMethodAttribs; } - } diff --git a/lib/Braintree/UsBankAccount.php b/lib/Braintree/UsBankAccount.php index 59da7ff..0fb362f 100644 --- a/lib/Braintree/UsBankAccount.php +++ b/lib/Braintree/UsBankAccount.php @@ -1,4 +1,5 @@ _attributes) . ']'; diff --git a/lib/Braintree/UsBankAccountGateway.php b/lib/Braintree/UsBankAccountGateway.php index 0dab854..3c8aef2 100644 --- a/lib/Braintree/UsBankAccountGateway.php +++ b/lib/Braintree/UsBankAccountGateway.php @@ -1,4 +1,5 @@ _attributes) . ']'; } diff --git a/lib/Braintree/UsBankAccountVerificationGateway.php b/lib/Braintree/UsBankAccountVerificationGateway.php index ebfe602..918f12b 100644 --- a/lib/Braintree/UsBankAccountVerificationGateway.php +++ b/lib/Braintree/UsBankAccountVerificationGateway.php @@ -1,4 +1,5 @@ _config->merchantPath() . '/us_bank_account_verifications/' . $token . '/confirm_micro_transfer_amounts'; $response = $this->_http->put($path, [ "us_bank_account_verification" => ["deposit_amounts" => $amounts] @@ -113,7 +115,7 @@ private function _verifyGatewayResponse($response) { if (isset($response['apiErrorResponse'])) { return new Result\Error($response['apiErrorResponse']); - } else if (isset($response['usBankAccountVerification'])) { + } elseif (isset($response['usBankAccountVerification'])) { // return a populated instance of UsBankAccountVerification return new Result\Successful( UsBankAccountVerification::factory($response['usBankAccountVerification']) diff --git a/lib/Braintree/UsBankAccountVerificationSearch.php b/lib/Braintree/UsBankAccountVerificationSearch.php index ad4ad53..a3c22e9 100644 --- a/lib/Braintree/UsBankAccountVerificationSearch.php +++ b/lib/Braintree/UsBankAccountVerificationSearch.php @@ -1,33 +1,41 @@ 'creditCard', - 'Braintree_CreditCard' => 'creditCard', 'Braintree\CreditCardGateway' => 'creditCard', - 'Braintree_CreditCardGateway' => 'creditCard', 'Braintree\Customer' => 'customer', - 'Braintree_Customer' => 'customer', 'Braintree\CustomerGateway' => 'customer', - 'Braintree_CustomerGateway' => 'customer', 'Braintree\Subscription' => 'subscription', - 'Braintree_Subscription' => 'subscription', 'Braintree\SubscriptionGateway' => 'subscription', - 'Braintree_SubscriptionGateway' => 'subscription', 'Braintree\Transaction' => 'transaction', - 'Braintree_Transaction' => 'transaction', 'Braintree\TransactionGateway' => 'transaction', - 'Braintree_TransactionGateway' => 'transaction', 'Braintree\CreditCardVerification' => 'verification', - 'Braintree_CreditCardVerification' => 'verification', 'Braintree\CreditCardVerificationGateway' => 'verification', - 'Braintree_CreditCardVerificationGateway' => 'verification', 'Braintree\AddOn' => 'addOn', - 'Braintree_AddOn' => 'addOn', 'Braintree\AddOnGateway' => 'addOn', - 'Braintree_AddOnGateway' => 'addOn', 'Braintree\Discount' => 'discount', - 'Braintree_Discount' => 'discount', 'Braintree\DiscountGateway' => 'discount', - 'Braintree_DiscountGateway' => 'discount', 'Braintree\Dispute' => 'dispute', - 'Braintree_Dispute' => 'dispute', 'Braintree\Dispute\EvidenceDetails' => 'evidence', - 'Braintree_Dispute_EvidenceDetails' => 'evidence', 'Braintree\DocumentUpload' => 'documentUpload', - 'Braintree_DocumentUpload' => 'doumentUpload', 'Braintree\Plan' => 'plan', - 'Braintree_Plan' => 'plan', 'Braintree\PlanGateway' => 'plan', - 'Braintree_PlanGateway' => 'plan', 'Braintree\Address' => 'address', - 'Braintree_Address' => 'address', 'Braintree\AddressGateway' => 'address', - 'Braintree_AddressGateway' => 'address', 'Braintree\SettlementBatchSummary' => 'settlementBatchSummary', - 'Braintree_SettlementBatchSummary' => 'settlementBatchSummary', 'Braintree\SettlementBatchSummaryGateway' => 'settlementBatchSummary', - 'Braintree_SettlementBatchSummaryGateway' => 'settlementBatchSummary', 'Braintree\Merchant' => 'merchant', - 'Braintree_Merchant' => 'merchant', 'Braintree\MerchantGateway' => 'merchant', - 'Braintree_MerchantGateway' => 'merchant', 'Braintree\MerchantAccount' => 'merchantAccount', - 'Braintree_MerchantAccount' => 'merchantAccount', 'Braintree\MerchantAccountGateway' => 'merchantAccount', - 'Braintree_MerchantAccountGateway' => 'merchantAccount', 'Braintree\OAuthCredentials' => 'credentials', - 'Braintree_OAuthCredentials' => 'credentials', 'Braintree\OAuthResult' => 'result', - 'Braintree_OAuthResult' => 'result', 'Braintree\PayPalAccount' => 'paypalAccount', - 'Braintree_PayPalAccount' => 'paypalAccount', 'Braintree\PayPalAccountGateway' => 'paypalAccount', - 'Braintree_PayPalAccountGateway' => 'paypalAccount', 'Braintree\UsBankAccountVerification' => 'usBankAccountVerification', - 'Braintree_UsBankAccountVerification' => 'usBankAccountVerification', ]; return $classNamesToResponseKeys[$name]; @@ -348,7 +317,7 @@ public static function implodeAssociativeArray($array, $separator = '=', $glue = { // build a new array with joined keys and values $tmpArray = null; - foreach ($array AS $key => $value) { + foreach ($array as $key => $value) { if ($value instanceof DateTime) { $value = $value->format('r'); } @@ -358,12 +327,13 @@ public static function implodeAssociativeArray($array, $separator = '=', $glue = return (is_array($tmpArray)) ? implode($glue, $tmpArray) : false; } - public static function attributesToString($attributes) { + public static function attributesToString($attributes) + { $printableAttribs = []; - foreach ($attributes AS $key => $value) { + foreach ($attributes as $key => $value) { if (is_array($value)) { $pAttrib = self::attributesToString($value); - } else if ($value instanceof DateTime) { + } elseif ($value instanceof DateTime) { $pAttrib = $value->format(DateTime::RFC850); } else { $pAttrib = $value; @@ -389,12 +359,29 @@ public static function verifyKeys($signature, $attributes) $invalidKeys = array_diff($userKeys, $validKeys); $invalidKeys = self::_removeWildcardKeys($validKeys, $invalidKeys); - if(!empty($invalidKeys)) { + if (!empty($invalidKeys)) { asort($invalidKeys); $sortedList = join(', ', $invalidKeys); throw new InvalidArgumentException('invalid keys: ' . $sortedList); } } + + /** + * replaces the value of a key in an array + * @param $array + * @param string $oldKey + * @param string $newKey + * @return array + */ + public static function replaceKey($array, $oldKey, $newKey) + { + if (array_key_exists($oldKey, $array)) { + $array[$newKey] = $array[$oldKey]; + unset($array[$oldKey]); + } + return $array; + } + /** * flattens a numerically indexed nested array to a single level * @param array $keys @@ -404,8 +391,8 @@ public static function verifyKeys($signature, $attributes) private static function _flattenArray($keys, $namespace = null) { $flattenedArray = []; - foreach($keys AS $key) { - if(is_array($key)) { + foreach ($keys as $key) { + if (is_array($key)) { $theKeys = array_keys($key); $theValues = array_values($key); $scope = $theKeys[0]; @@ -422,25 +409,25 @@ private static function _flattenArray($keys, $namespace = null) private static function _flattenUserKeys($keys, $namespace = null) { - $flattenedArray = []; - - foreach($keys AS $key => $value) { - $fullKey = empty($namespace) ? $key : $namespace; - if (!is_numeric($key) && $namespace != null) { - $fullKey .= '[' . $key . ']'; - } - if (is_numeric($key) && is_string($value)) { - $fullKey .= '[' . $value . ']'; - } - if(is_array($value)) { - $more = self::_flattenUserKeys($value, $fullKey); - $flattenedArray = array_merge($flattenedArray, $more); - } else { - $flattenedArray[] = $fullKey; - } - } - sort($flattenedArray); - return $flattenedArray; + $flattenedArray = []; + + foreach ($keys as $key => $value) { + $fullKey = empty($namespace) ? $key : $namespace; + if (!is_numeric($key) && $namespace != null) { + $fullKey .= '[' . $key . ']'; + } + if (is_numeric($key) && is_string($value)) { + $fullKey .= '[' . $value . ']'; + } + if (is_array($value)) { + $more = self::_flattenUserKeys($value, $fullKey); + $flattenedArray = array_merge($flattenedArray, $more); + } else { + $flattenedArray[] = $fullKey; + } + } + sort($flattenedArray); + return $flattenedArray; } /** @@ -451,10 +438,10 @@ private static function _flattenUserKeys($keys, $namespace = null) */ private static function _removeWildcardKeys($validKeys, $invalidKeys) { - foreach($validKeys AS $key) { + foreach ($validKeys as $key) { if (stristr($key, '[_anyKey_]')) { $wildcardKey = str_replace('[_anyKey_]', '', $key); - foreach ($invalidKeys AS $index => $invalidKey) { + foreach ($invalidKeys as $index => $invalidKey) { if (stristr($invalidKey, $wildcardKey)) { unset($invalidKeys[$index]); } diff --git a/lib/Braintree/VenmoAccount.php b/lib/Braintree/VenmoAccount.php index 6ccf934..bb24ced 100644 --- a/lib/Braintree/VenmoAccount.php +++ b/lib/Braintree/VenmoAccount.php @@ -1,4 +1,5 @@ == More information == * + * // phpcs:ignore Generic.Files.LineLength * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php} * * @package Braintree @@ -84,7 +86,7 @@ protected function _initialize($creditCardAttribs) $subscriptionArray = []; if (isset($creditCardAttribs['subscriptions'])) { - foreach ($creditCardAttribs['subscriptions'] AS $subscription) { + foreach ($creditCardAttribs['subscriptions'] as $subscription) { $subscriptionArray[] = Subscription::factory($subscription); } } @@ -94,7 +96,7 @@ protected function _initialize($creditCardAttribs) $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); $this->_set('maskedNumber', $this->bin . '******' . $this->last4); - if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { + if (isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) { $verifications = $creditCardAttribs['verifications']; usort($verifications, [$this, '_compareCreatedAtOnVerifications']); @@ -124,10 +126,10 @@ public function isEqual($otherVisaCheckoutCard) * ClassName[property=value, property=value] * @return string */ - public function __toString() + public function __toString() { return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; + Util::attributesToString($this->_attributes) . ']'; } /** diff --git a/lib/Braintree/WebhookNotification.php b/lib/Braintree/WebhookNotification.php index 3da7efa..326ba3a 100644 --- a/lib/Braintree/WebhookNotification.php +++ b/lib/Braintree/WebhookNotification.php @@ -1,8 +1,32 @@ webhookNotification()->parse($signature, $payload); } - public static function verify($challenge) { + public static function verify($challenge) + { return Configuration::gateway()->webhookNotification()->verify($challenge); } @@ -54,6 +60,7 @@ public static function factory($attributes) protected function _initialize($attributes) { + // phpcs:disable Generic.Files.LineLength $this->_attributes = $attributes; if (!isset($attributes['sourceMerchantId'])) { @@ -118,9 +125,14 @@ protected function _initialize($attributes) $this->_set('localPaymentCompleted', LocalPaymentCompleted::factory($wrapperNode['localPayment'])); } + if (isset($wrapperNode['localPaymentReversed'])) { + $this->_set('localPaymentReversed', LocalPaymentReversed::factory($wrapperNode['localPaymentReversed'])); + } + if (isset($wrapperNode['errors'])) { $this->_set('errors', new Error\ValidationErrorCollection($wrapperNode['errors'])); $this->_set('message', $wrapperNode['message']); } + // phpcs:enable Generic.Files.LineLength } } diff --git a/lib/Braintree/WebhookNotificationGateway.php b/lib/Braintree/WebhookNotificationGateway.php index 1b5e8d8..22bf07b 100644 --- a/lib/Braintree/WebhookNotificationGateway.php +++ b/lib/Braintree/WebhookNotificationGateway.php @@ -1,4 +1,5 @@ config->getPublicKey()) { return $components[1]; diff --git a/lib/Braintree/WebhookTesting.php b/lib/Braintree/WebhookTesting.php index 3203d5b..5a473f4 100644 --- a/lib/Braintree/WebhookTesting.php +++ b/lib/Braintree/WebhookTesting.php @@ -1,4 +1,5 @@ config->getPublicKey() . "|" . Digest::hexDigestSha1($this->config->getPrivateKey(), $payload); + $publicKey = $this->config->getPublicKey(); + $sha = Digest::hexDigestSha1($this->config->getPrivateKey(), $payload); + $signature = $publicKey . "|" . $sha; return [ 'bt_signature' => $signature, @@ -88,6 +91,15 @@ private static function _sampleXml($kind, $id, $sourceMerchantId) case WebhookNotification::SUBSCRIPTION_CHARGED_UNSUCCESSFULLY: $subjectXml = self::_subscriptionChargedUnsuccessfullySampleXml($id); break; + case WebhookNotification::SUBSCRIPTION_EXPIRED: + $subjectXml = self::_subscriptionExpiredSampleXml($id); + break; + case WebhookNotification::SUBSCRIPTION_CANCELED: + $subjectXml = self::_subscriptionCanceledSampleXml($id); + break; + case WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE: + $subjectXml = self::_subscriptionWentPastDueSampleXml($id); + break; case WebhookNotification::CHECK: $subjectXml = self::_checkSampleXml(); break; @@ -100,12 +112,18 @@ private static function _sampleXml($kind, $id, $sourceMerchantId) case WebhookNotification::RECIPIENT_UPDATED_GRANTED_PAYMENT_METHOD: $subjectXml = self::_grantedPaymentInstrumentUpdateSampleXml(); break; + case WebhookNotification::GRANTED_PAYMENT_METHOD_REVOKED: + $subjectXml = self::_grantedPaymentMethodRevokedXml($id); + break; case WebhookNotification::PAYMENT_METHOD_REVOKED_BY_CUSTOMER: $subjectXml = self::_paymentMethodRevokedByCustomerSampleXml($id); break; case WebhookNotification::LOCAL_PAYMENT_COMPLETED: $subjectXml = self::_localPaymentCompletedSampleXml(); break; + case WebhookNotification::LOCAL_PAYMENT_REVERSED: + $subjectXml = self::_localPaymentReversedSampleXml(); + break; default: $subjectXml = self::_subscriptionSampleXml($id); break; @@ -420,6 +438,7 @@ private static function _subscriptionSampleXml($id) return " {$id} + Active @@ -435,6 +454,7 @@ private static function _subscriptionChargedSuccessfullySampleXml($id) return " {$id} + Active 2016-03-21 2017-03-31 @@ -457,6 +477,7 @@ private static function _subscriptionChargedUnsuccessfullySampleXml($id) return " {$id} + Active 2016-03-21 2017-03-31 @@ -474,6 +495,54 @@ private static function _subscriptionChargedUnsuccessfullySampleXml($id) "; } + private static function _subscriptionExpiredSampleXml($id) + { + return " + + {$id} + Expired + + + + + + + + "; + } + + private static function _subscriptionCanceledSampleXml($id) + { + return " + + {$id} + Canceled + + + + + + + + "; + } + + private static function _subscriptionWentPastDueSampleXml($id) + { + return " + + {$id} + Past Due + + + + + + + + "; + } + private static function _checkSampleXml() { return " @@ -555,7 +624,7 @@ private static function _connectedMerchantPayPalStatusChangedSampleXml($id) } private static function _grantedPaymentInstrumentUpdateSampleXml() - { + { return " vczo7jqrpwrsi2px @@ -574,6 +643,25 @@ private static function _grantedPaymentInstrumentUpdateSampleXml() "; } + private static function _grantedPaymentMethodRevokedXml($id) + { + return " + + 2018-10-11T21:28:37Z + 2018-10-11T21:28:37Z + true + https://assets.braintreegateway.com/payment_method_logo/venmo.png?environment=test + {$id} + Venmo Account: venmojoe + venmojoe + 456 + + venmo_customer_id + cGF5bWVudG1ldGhvZF92ZW5tb2FjY291bnQ + + "; + } + private static function _paymentMethodRevokedByCustomerSampleXml($id) { return " @@ -598,7 +686,7 @@ private static function _paymentMethodRevokedByCustomerSampleXml($id) } private static function _localPaymentCompletedSampleXml() - { + { return " a-payment-id @@ -614,6 +702,15 @@ private static function _localPaymentCompletedSampleXml() "; } + private static function _localPaymentReversedSampleXml() + { + return " + + a-payment-id + + "; + } + private static function _timestamp() { $originalZone = date_default_timezone_get(); diff --git a/lib/Braintree/Xml.php b/lib/Braintree/Xml.php index 782a0d1..ee04924 100644 --- a/lib/Braintree/Xml.php +++ b/lib/Braintree/Xml.php @@ -1,4 +1,5 @@ text($aData); } - return; + return; } - foreach ($aData AS $elementName => $element) { + foreach ($aData as $elementName => $element) { // handle child elements $writer->startElement($elementName); if (is_array($element)) { if (array_key_exists(0, $element) || empty($element)) { $writer->writeAttribute('type', 'array'); - foreach ($element AS $ignored => $itemInArray) { + foreach ($element as $ignored => $itemInArray) { $writer->startElement('item'); self::_createElementsFromArray($writer, $itemInArray); $writer->endElement(); } - } - else { + } else { self::_createElementsFromArray($writer, $element); } } else { @@ -101,8 +101,8 @@ private static function _createElementsFromArray(&$writer, $aData) */ private static function _generateXmlAttribute($value) { - if ($value instanceof DateTime) { - return ['type', 'datetime', self::_dateTimeToXmlTimestamp($value)]; + if ($value instanceof DateTime || is_a($value, 'DateTimeImmutable')) { + return ['type', 'datetime', self::_convertDateTimeObjectToXmlTimestamp($value)]; } if (is_int($value)) { return ['type', 'integer', $value]; @@ -110,7 +110,7 @@ private static function _generateXmlAttribute($value) if (is_bool($value)) { return ['type', 'boolean', ($value ? 'true' : 'false')]; } - if ($value === NULL) { + if ($value === null) { return ['nil', 'true', $value]; } } @@ -120,9 +120,13 @@ private static function _generateXmlAttribute($value) * @param object $dateTime * @return string XML schema formatted timestamp */ - private static function _dateTimeToXmlTimestamp($dateTime) + private static function _convertDateTimeObjectToXmlTimestamp($dateTime) { - $dateTimeForUTC = clone $dateTime; + if (is_a($dateTime, 'DateTimeImmutable')) { + $dateTimeForUTC = DateTime::createFromImmutable($dateTime); + } else { + $dateTimeForUTC = clone $dateTime; + } $dateTimeForUTC->setTimeZone(new DateTimeZone('UTC')); return ($dateTimeForUTC->format('Y-m-d\TH:i:s') . 'Z'); @@ -132,10 +136,10 @@ private static function _castDateTime($string) { try { if (empty($string)) { - return false; + return false; } $dateTime = new DateTime($string); - return self::_dateTimeToXmlTimestamp($dateTime); + return self::_convertDateTimeObjectToXmlTimestamp($dateTime); } catch (Exception $e) { // not a datetime return false; diff --git a/lib/Braintree/Xml/Parser.php b/lib/Braintree/Xml/Parser.php index 7218dbb..0614c79 100644 --- a/lib/Braintree/Xml/Parser.php +++ b/lib/Braintree/Xml/Parser.php @@ -1,4 +1,5 @@ getAttribute('type'); } - switch($type) { - case 'array': - $array = []; - foreach ($node->childNodes as $child) { - $value = self::_nodeToValue($child); - if ($value !== null) { - $array[] = $value; - } - } - return $array; - case 'collection': - $collection = []; - foreach ($node->childNodes as $child) { - $value = self::_nodetoValue($child); - if ($value !== null) { - if (!isset($collection[$child->nodeName])) { - $collection[$child->nodeName] = []; + switch ($type) { + case 'array': + $array = []; + foreach ($node->childNodes as $child) { + $value = self::_nodeToValue($child); + if ($value !== null) { + $array[] = $value; } - $collection[$child->nodeName][] = self::_nodeToValue($child); } - } - return $collection; - default: - $values = []; - if ($node->childNodes->length === 1 && $node->childNodes->item(0) instanceof DOMText) { - return $node->childNodes->item(0)->nodeValue; - } else { + return $array; + case 'collection': + $collection = []; foreach ($node->childNodes as $child) { - if (!$child instanceof DOMText) { - $values[$child->nodeName] = self::_nodeToValue($child); + $value = self::_nodetoValue($child); + if ($value !== null) { + if (!isset($collection[$child->nodeName])) { + $collection[$child->nodeName] = []; + } + $collection[$child->nodeName][] = self::_nodeToValue($child); } } - return $values; - } + return $collection; + default: + $values = []; + if ($node->childNodes->length === 1 && $node->childNodes->item(0) instanceof DOMText) { + return $node->childNodes->item(0)->nodeValue; + } else { + foreach ($node->childNodes as $child) { + if (!$child instanceof DOMText) { + $values[$child->nodeName] = self::_nodeToValue($child); + } + } + return $values; + } } } @@ -94,31 +95,31 @@ private static function _nodeToValue($node) $type = $node->getAttribute('type'); } - switch($type) { - case 'datetime': - return self::_timestampToUTC((string) $node->nodeValue); - case 'date': - return new DateTime((string) $node->nodeValue); - case 'integer': - return (int) $node->nodeValue; - case 'boolean': - $value = (string) $node->nodeValue; - if(is_numeric($value)) { - return (bool) $value; - } else { - return ($value !== "true") ? false : true; - } - case 'array': - case 'collection': - return self::_nodeToArray($node); - default: - if ($node->hasChildNodes()) { + switch ($type) { + case 'datetime': + return self::_timestampToUTC((string) $node->nodeValue); + case 'date': + return new DateTime((string) $node->nodeValue); + case 'integer': + return (int) $node->nodeValue; + case 'boolean': + $value = (string) $node->nodeValue; + if (is_numeric($value)) { + return (bool) $value; + } else { + return ($value !== "true") ? false : true; + } + case 'array': + case 'collection': return self::_nodeToArray($node); - } elseif (trim($node->nodeValue) === '') { - return null; - } else { - return $node->nodeValue; - } + default: + if ($node->hasChildNodes()) { + return self::_nodeToArray($node); + } elseif (trim($node->nodeValue) === '') { + return null; + } else { + return $node->nodeValue; + } } } From bb2b1e73d1e3d922001f63f1e09c251cae0d7c48 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 12 Jul 2021 12:32:16 +0530 Subject: [PATCH 89/99] Updates changelog and version for v4.0.2 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 1ae52f1..008c9fc 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0.1 + * Version: 4.0.2 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0.1'; + public static $version = '4.0.2'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index ccc42af..32c23ed 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0.1'; + protected $_version = '4.0.2'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index c7741a9..6cbc186 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 -Tested up to: 5.6.2 -Stable tag: 4.0.1 +Tested up to: 5.7.2 +Stable tag: 4.0.2 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.2 - 07.12.2021 = +* Tweak - Updates Update Braintree SDK. ([GFB-37](https://github.com/angelleye/gravity-forms-braintree/pull/33)) + = 4.0.1 - 03.16.2021 = * Tweak - Adding label for Braintree CC while setting up Subscription method ([GFB-36](https://github.com/angelleye/gravity-forms-braintree/pull/31)) From 9226888df8d8d311cf6e2a951275e64c5cee001a Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 6 Jan 2022 18:53:03 +0530 Subject: [PATCH 90/99] Fatal Error Gravity Form, GFB-41 --- lib/class.plugify-gform-braintree.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 32c23ed..64c5395 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -879,19 +879,14 @@ public function plugin_settings_fields () { * @return void */ public function settings_are_valid ( $settings ) { - if( empty( $settings ) ) { return false; } - - foreach( $settings as $setting ) { - if( '' == $setting ) { - return false; - } + if(!empty($settings['merchant-id']) && !empty($settings['public-key']) && !empty($settings['public-key'])) { + return true; + } else { + return false; } - - return true; - } /** From ea7882eb584bf666b02c9c049440409e9e29a4dd Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 10 Jan 2022 12:51:30 +0530 Subject: [PATCH 91/99] Updates changelog and version for v4.0.3 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 008c9fc..39c10d3 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0.2 + * Version: 4.0.3 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0.2'; + public static $version = '4.0.3'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 64c5395..dbf295b 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0.2'; + protected $_version = '4.0.3'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index 6cbc186..e293b8c 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 -Tested up to: 5.7.2 -Stable tag: 4.0.2 +Tested up to: 5.8.3 +Stable tag: 4.0.3 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.3 - 01.10.2022 = +* Fix - Resolved PHP Fatal error. ([GFB-37](https://github.com/angelleye/gravity-forms-braintree/pull/37)) + = 4.0.2 - 07.12.2021 = * Tweak - Updates Update Braintree SDK. ([GFB-37](https://github.com/angelleye/gravity-forms-braintree/pull/33)) From 92e7038a22108a161624534a1a7e31afadf57610 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 17 Jan 2022 15:42:43 +0530 Subject: [PATCH 92/99] Fatal Error Gravity Form, GFB-41 --- lib/class.plugify-gform-braintree.php | 1595 ++++++++++++------------- 1 file changed, 766 insertions(+), 829 deletions(-) diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 64c5395..ed61f2c 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -5,7 +5,6 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { protected $_version = '4.0.2'; - protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; protected $_path = 'gravity-forms-braintree/lib/class.plugify-gform-braintree.php'; @@ -17,7 +16,6 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { protected $_enable_rg_autoupgrade = true; protected $is_payment_gateway = true; protected $current_feed = true; - protected $selected_payment_method = 'creditcard'; /** @@ -25,46 +23,46 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { * @since 1.0 * @return void */ - public function __construct () { + public function __construct() { add_action('wp_ajax_angelleye_gform_braintree_adismiss_notice', array($this, 'angelleye_gform_braintree_adismiss_notice'), 10); add_action('admin_notices', array($this, 'angelleye_gform_braintree_display_push_notification'), 10); add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_css'), 10); add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_js'), 10); - add_filter( 'gform_noconflict_scripts', [$this, 'include_angelleye_braintree_script_noconflict'] ); - add_filter( 'gform_noconflict_styles', [$this, 'include_angelleye_braintree_style_noconflict'] ); + add_filter('gform_noconflict_scripts', [$this, 'include_angelleye_braintree_script_noconflict']); + add_filter('gform_noconflict_styles', [$this, 'include_angelleye_braintree_style_noconflict']); // Build parent parent::__construct(); } - /** - * Override credit card field check, so that we can return true when someone has ach form - * If any user will have any form then same payment gateway class will be used - * @param array $form - * - * @return bool - */ - public function has_credit_card_field( $form ) { - if(isset($form['fields'])) { - foreach ($form['fields'] as $single_field) { - if ($single_field->type == 'creditcard' || $single_field->type=='braintree_ach' || $single_field->type=='braintree_credit_card') { - return true; - } - } - } - return $this->get_credit_card_field( $form ) !== false; - } - - /** - * Override default message for Gravity Form Braintree Feeds - * @return string - */ - public function requires_credit_card_message() { - $url = add_query_arg( array( 'view' => null, 'subview' => null ) ); - - return sprintf( esc_html__( "You must add a Credit Card/ACH Payment field to your form before creating a feed. Let's go %sadd one%s!", 'gravityforms' ), "", '' ); - } + /** + * Override credit card field check, so that we can return true when someone has ach form + * If any user will have any form then same payment gateway class will be used + * @param array $form + * + * @return bool + */ + public function has_credit_card_field($form) { + if (isset($form['fields'])) { + foreach ($form['fields'] as $single_field) { + if ($single_field->type == 'creditcard' || $single_field->type == 'braintree_ach' || $single_field->type == 'braintree_credit_card') { + return true; + } + } + } + return $this->get_credit_card_field($form) !== false; + } + + /** + * Override default message for Gravity Form Braintree Feeds + * @return string + */ + public function requires_credit_card_message() { + $url = add_query_arg(array('view' => null, 'subview' => null)); + + return sprintf(esc_html__("You must add a Credit Card/ACH Payment field to your form before creating a feed. Let's go %sadd one%s!", 'gravityforms'), "", ''); + } /** * Override init_frontend to assign front end based filters and actions required for operation @@ -72,274 +70,260 @@ public function requires_credit_card_message() { * @since 1.0 * @return void */ - public function init_frontend () { + public function init_frontend() { // init_frontend on GFPaymentAddOn parent::init_frontend(); + } + + /** + * Init the Braintree configuration and return gateway for transactions, etc. + * @return bool|\Braintree\Gateway + * @throws \Braintree\Exception\Configuration + */ + public function getBraintreeGateway() { + $settings = $this->get_plugin_settings(); + if (!$settings) + return false; + + // Configure Braintree environment + $braintree_config = new \Braintree\Configuration([ + 'environment' => strtolower($settings['environment']), + 'merchantId' => $settings['merchant-id'], + 'publicKey' => $settings['public-key'], + 'privateKey' => $settings['private-key'] + ]); + + $braintree_config->timeout(60); + + $gateway = new Braintree\Gateway($braintree_config); + return $gateway; + } + + /** + * ACH Payment authorization + * @param $feed + * @param $submission_data + * @param $form + * @param $entry + * + * @return array|bool + * @throws \Braintree\Exception\Configuration + */ + public function ach_authorize($feed, $submission_data, $form, $entry) { + $this->log_debug("Braintree_ACH_Authorize::START"); + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + try { + // Prepare authorization response payload + $authorization = array( + 'is_authorized' => false, + 'error_message' => apply_filters('gform_braintree_credit_card_failure_message', __('We are unable to authorize the bank account, Please try again.', 'gravity-forms-braintree')), + 'transaction_id' => '', + 'captured_payment' => array( + 'is_success' => false, + 'error_message' => '', + 'transaction_id' => '', + 'amount' => $submission_data['payment_amount'] + ) + ); + + $ach_device_corelation = rgpost('ach_device_corelation'); + $ach_token = rgpost('ach_token'); + $payment_amount = number_format($submission_data['payment_amount'], 2, '.', ''); + + $settings = $this->get_plugin_settings(); + $response = getAngelleyeBraintreePaymentFields($form); + $braintree_ach_field = $response['braintree_ach']; + /* $account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); + $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); + $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' ); */ + $account_holder_name = rgpost('input_' . $braintree_ach_field->id . '_4'); + + $account_holder_name = explode(' ', $account_holder_name); + /** + * Create customer in Braintree + */ + $customer_request = [ + 'firstName' => @$account_holder_name[0], + 'lastName' => end($account_holder_name), + ]; + $this->log_debug("Braintree_ACH_Customer::create REQUEST => " . print_r($customer_request, 1)); + $customer_result = $gateway->customer()->create($customer_request); + $this->log_debug("Braintree_ACH_Customer::create RESPONSE => " . print_r($customer_result, 1)); + + if ($customer_result->success) { + $payment_method_request = [ + 'customerId' => $customer_result->customer->id, + 'paymentMethodNonce' => $ach_token, + 'options' => [ + 'usBankAccountVerificationMethod' => Braintree\Result\UsBankAccountVerification::NETWORK_CHECK + ] + ]; + + $this->log_debug("Braintree_ACH_PaymentRequest::create REQUEST => " . print_r($payment_method_request, 1)); + $payment_method_response = $gateway->paymentMethod()->create($payment_method_request); + $this->log_debug("Braintree_ACH_PaymentRequest::create RESPONSE => " . print_r($payment_method_response, 1)); + + if (isset($payment_method_response->paymentMethod->token)) { + + $sale_request = [ + 'amount' => $payment_amount, + 'paymentMethodToken' => $payment_method_response->paymentMethod->token, + 'deviceData' => $ach_device_corelation, + 'options' => [ + 'submitForSettlement' => true + ] + ]; + + $sale_request = apply_filters('angelleye_braintree_parameter', $sale_request, $submission_data, $form, $entry); + + $this->log_debug("Braintree_ACH_Transaction::sale REQUEST => " . print_r($sale_request, 1)); + $sale_response = $gateway->transaction()->sale($sale_request); + $this->log_debug("Braintree_ACH_Transaction::sale RESPONSE => " . print_r($sale_response, 1)); + + if ($sale_response->success) { + do_action('angelleye_gravity_forms_response_data', $sale_response, $submission_data, '16', ( strtolower($settings['environment']) == 'sandbox' ) ? true : false, false, 'braintree_ach'); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $sale_response->transaction->id; + + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $sale_response->transaction->id, + 'amount' => $sale_response->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Braintree ACH' + ); + + $this->log_debug("Braintree_ACH::SUCCESS"); + } else { + if (isset($sale_response->transaction->processorResponseText)) { + $authorization['error_message'] = sprintf('Your bank did not authorized the transaction: %s.', $sale_response->transaction->processorResponseText); + } else { + $authorization['error_message'] = sprintf('Your bank declined the transaction, please try again or contact bank.'); + } + $this->log_debug("Braintree_ACH::FAILED_ERROR"); + } + } else { + $authorization['error_message'] = __('We are unable to authorize bank account, This may have happened due to expired token, please try again.', 'gravity-forms-braintree'); + } + } else { + $authorization['error_message'] = __('Unable to proceed with the transaction due to invalid name.', 'gravity-forms-braintree'); + } + } catch (Exception $exception) { + $this->log_debug("Braintree_ACH::EXCEPTION: " . $exception->getTraceAsString()); + $exception['error_message'] = __('An internal error occurred, Please try later. ERROR: ' . $exception->getMessage()); + } + return $authorization; + } + $this->log_debug("Braintree_ACH::FAILED"); + return false; } - /** - * Init the Braintree configuration and return gateway for transactions, etc. - * @return bool|\Braintree\Gateway - * @throws \Braintree\Exception\Configuration - */ - public function getBraintreeGateway() { - $settings = $this->get_plugin_settings(); - if(!$settings) - return false; - - // Configure Braintree environment - $braintree_config = new \Braintree\Configuration([ - 'environment' => strtolower( $settings['environment'] ) , - 'merchantId' => $settings['merchant-id'], - 'publicKey' => $settings['public-key'], - 'privateKey' => $settings['private-key'] - ]); - - $braintree_config->timeout(60); - - $gateway = new Braintree\Gateway($braintree_config); - return $gateway; + /** + * Gets the payment validation result. + * + * @since Unknown + * @access public + * + * @used-by GFPaymentAddOn::validation() + * + * @param array $validation_result Contains the form validation results. + * @param array $authorization_result Contains the form authorization results. + * + * @return array The validation result for the credit card field. + */ + public function get_validation_result($validation_result, $authorization_result) { + + $credit_card_page = 0; + if ($this->selected_payment_method == 'braintree_ach') { + foreach ($validation_result['form']['fields'] as &$field) { + if ($field->type == 'braintree_ach') { + $field->failed_validation = true; + $field->validation_message = $authorization_result['error_message']; + $credit_card_page = $field->pageNumber; + break; + } + } + } else { + foreach ($validation_result['form']['fields'] as &$field) { + if ($field->type == 'creditcard') { + $field->failed_validation = true; + $field->validation_message = $authorization_result['error_message']; + $credit_card_page = $field->pageNumber; + break; + } + } + } + $validation_result['credit_card_page'] = $credit_card_page; + $validation_result['is_valid'] = false; + + return $validation_result; } - /** - * ACH Payment authorization - * @param $feed - * @param $submission_data - * @param $form - * @param $entry - * - * @return array|bool - * @throws \Braintree\Exception\Configuration - */ - public function ach_authorize( $feed, $submission_data, $form, $entry ) { - $this->log_debug( "Braintree_ACH_Authorize::START" ); - // Prepare authorization response payload - $authorization = array( - 'is_authorized' => false, - 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'We are unable to authorize the bank account, Please try again.', 'gravity-forms-braintree' ) ), - 'transaction_id' => '', - 'captured_payment' => array( - 'is_success' => false, - 'error_message' => '', - 'transaction_id' => '', - 'amount' => $submission_data['payment_amount'] - ) - ); - - $ach_device_corelation = rgpost('ach_device_corelation'); - $ach_token = rgpost('ach_token'); - $payment_amount = number_format($submission_data['payment_amount'],2,'.',''); - - $gateway = $this->getBraintreeGateway(); - if( $gateway !== false ) { - try { - $settings = $this->get_plugin_settings(); - $response = getAngelleyeBraintreePaymentFields( $form ); - $braintree_ach_field = $response['braintree_ach']; - /*$account_number = rgpost( 'input_' . $braintree_ach_field->id . '_1' ); - $account_type = rgpost( 'input_' . $braintree_ach_field->id . '_2' ); - $routing_number = rgpost( 'input_' . $braintree_ach_field->id . '_3' );*/ - $account_holder_name = rgpost( 'input_' . $braintree_ach_field->id . '_4' ); - - $account_holder_name = explode( ' ', $account_holder_name ); - /** - * Create customer in Braintree - */ - $customer_request = [ - 'firstName' => @$account_holder_name[0], - 'lastName' => end( $account_holder_name ), - ]; - $this->log_debug( "Braintree_ACH_Customer::create REQUEST => " . print_r( $customer_request, 1 ) ); - $customer_result = $gateway->customer()->create( $customer_request ); - $this->log_debug( "Braintree_ACH_Customer::create RESPONSE => " . print_r( $customer_result, 1 ) ); - - if ( $customer_result->success ) { - $payment_method_request = [ - 'customerId' => $customer_result->customer->id, - 'paymentMethodNonce' => $ach_token, - 'options' => [ - 'usBankAccountVerificationMethod' => Braintree\Result\UsBankAccountVerification::NETWORK_CHECK - ] - ]; - - $this->log_debug( "Braintree_ACH_PaymentRequest::create REQUEST => " . print_r( $payment_method_request, 1 ) ); - $payment_method_response = $gateway->paymentMethod()->create( $payment_method_request ); - $this->log_debug( "Braintree_ACH_PaymentRequest::create RESPONSE => " . print_r( $payment_method_response, 1 ) ); - - if ( isset( $payment_method_response->paymentMethod->token ) ) { - - $sale_request = [ - 'amount' => $payment_amount, - 'paymentMethodToken' => $payment_method_response->paymentMethod->token, - 'deviceData' => $ach_device_corelation, - 'options' => [ - 'submitForSettlement' => true - ] - ]; - - $sale_request = apply_filters('angelleye_braintree_parameter', $sale_request, $submission_data, $form, $entry); - - $this->log_debug( "Braintree_ACH_Transaction::sale REQUEST => " . print_r( $sale_request, 1 ) ); - $sale_response = $gateway->transaction()->sale( $sale_request ); - $this->log_debug( "Braintree_ACH_Transaction::sale RESPONSE => " . print_r( $sale_response, 1 ) ); - - if ( $sale_response->success ) { - do_action( 'angelleye_gravity_forms_response_data', $sale_response, $submission_data, '16', ( strtolower( $settings['environment'] ) == 'sandbox' ) ? true : false, false, 'braintree_ach' ); - $authorization['is_authorized'] = true; - $authorization['error_message'] = ''; - $authorization['transaction_id'] = $sale_response->transaction->id; - - $authorization['captured_payment'] = array( - 'is_success' => true, - 'transaction_id' => $sale_response->transaction->id, - 'amount' => $sale_response->transaction->amount, - 'error_message' => '', - 'payment_method' => 'Braintree ACH' - ); - - $this->log_debug( "Braintree_ACH::SUCCESS" ); - } else { - if ( isset( $sale_response->transaction->processorResponseText ) ) { - $authorization['error_message'] = sprintf( 'Your bank did not authorized the transaction: %s.', $sale_response->transaction->processorResponseText ); - } else { - $authorization['error_message'] = sprintf( 'Your bank declined the transaction, please try again or contact bank.' ); - } - $this->log_debug( "Braintree_ACH::FAILED_ERROR" ); - } - } else { - $authorization['error_message'] = __( 'We are unable to authorize bank account, This may have happened due to expired token, please try again.', 'gravity-forms-braintree' ); - } - } else { - $authorization['error_message'] = __( 'Unable to proceed with the transaction due to invalid name.', 'gravity-forms-braintree' ); - } - }catch (Exception $exception){ - $this->log_debug( "Braintree_ACH::EXCEPTION: ".$exception->getTraceAsString() ); - $exception['error_message'] = __('An internal error occurred, Please try later. ERROR: '.$exception->getMessage()); - } - return $authorization; - - } - - $this->log_debug( "Braintree_ACH::FAILED"); - return false; - } - - /** - * Gets the payment validation result. - * - * @since Unknown - * @access public - * - * @used-by GFPaymentAddOn::validation() - * - * @param array $validation_result Contains the form validation results. - * @param array $authorization_result Contains the form authorization results. - * - * @return array The validation result for the credit card field. - */ - public function get_validation_result( $validation_result, $authorization_result ) { - - $credit_card_page = 0; - if($this->selected_payment_method=='braintree_ach'){ - foreach ( $validation_result['form']['fields'] as &$field ) { - if ( $field->type == 'braintree_ach' ) { - $field->failed_validation = true; - $field->validation_message = $authorization_result['error_message']; - $credit_card_page = $field->pageNumber; - break; - } - } - }else { - foreach ( $validation_result['form']['fields'] as &$field ) { - if ( $field->type == 'creditcard' ) { - $field->failed_validation = true; - $field->validation_message = $authorization_result['error_message']; - $credit_card_page = $field->pageNumber; - break; - } - } - } - $validation_result['credit_card_page'] = $credit_card_page; - $validation_result['is_valid'] = false; - - return $validation_result; - - } - - /** - * Braintree credit card Payment authorization - * @param $feed - * @param $submission_data - * @param $form - * @param $entry - * - * @return array|bool - * @throws \Braintree\Exception\Configuration - */ - public function braintree_cc_authorize( $feed, $submission_data, $form, $entry ) { - - $authorization = array( - 'is_authorized' => false, - 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'Your card could not be billed. Please ensure the details you entered are correct and try again.', 'gravity-forms-braintree' ) ), - 'transaction_id' => '', - 'captured_payment' => array( - 'is_success' => false, - 'error_message' => '', - 'transaction_id' => '', - 'amount' => $submission_data['payment_amount'] - ) - ); - - if(empty($_POST['payment_method_nonce'])) { - return $authorization; - } - - try { - - $settings = $this->get_plugin_settings(); - $gateway = $this->getBraintreeGateway(); - - $args = array( - 'amount' => $submission_data['payment_amount'], - 'paymentMethodNonce' => $_POST['payment_method_nonce'] - ); - - $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); - - if( $settings['settlement'] == 'Yes' ) { - $args['options']['submitForSettlement'] = 'true'; - } - - $result = $gateway->transaction()->sale($args); - - if( $result->success ) { - do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree'); - $authorization['is_authorized'] = true; - $authorization['error_message'] = ''; - $authorization['transaction_id'] = $result->transaction->id; - - $authorization['captured_payment'] = array( - 'is_success' => true, - 'transaction_id' => $result->transaction->id, - 'amount' => $result->transaction->amount, - 'error_message' => '', - 'payment_method' => 'Credit Card' - ); - - } else { - if( isset( $result->transaction->processorResponseText ) ) { - $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); - } - } - - } catch( Exception $e ) { - // Do nothing with exception object, just fallback to generic failure - } - - return $authorization; - } + /** + * Braintree credit card Payment authorization + * @param $feed + * @param $submission_data + * @param $form + * @param $entry + * + * @return array|bool + * @throws \Braintree\Exception\Configuration + */ + public function braintree_cc_authorize($feed, $submission_data, $form, $entry) { + try { + $settings = $this->get_plugin_settings(); + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + $authorization = array( + 'is_authorized' => false, + 'error_message' => apply_filters('gform_braintree_credit_card_failure_message', __('Your card could not be billed. Please ensure the details you entered are correct and try again.', 'gravity-forms-braintree')), + 'transaction_id' => '', + 'captured_payment' => array( + 'is_success' => false, + 'error_message' => '', + 'transaction_id' => '', + 'amount' => $submission_data['payment_amount'] + ) + ); + if (empty($_POST['payment_method_nonce'])) { + return $authorization; + } + $args = array( + 'amount' => $submission_data['payment_amount'], + 'paymentMethodNonce' => $_POST['payment_method_nonce'] + ); + $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); + if ($settings['settlement'] == 'Yes') { + $args['options']['submitForSettlement'] = 'true'; + } + $result = $gateway->transaction()->sale($args); + if ($result->success) { + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false, false, 'braintree'); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $result->transaction->id; + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $result->transaction->id, + 'amount' => $result->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Credit Card' + ); + } else { + if (isset($result->transaction->processorResponseText)) { + $authorization['error_message'] .= sprintf('. Your bank said: %s.', $result->transaction->processorResponseText); + } + } + } + } catch (Exception $e) { + // Do nothing with exception object, just fallback to generic failure + } + return $authorization; + } /** * After form has been submitted, send CC details to Braintree and ensure the card is going to work @@ -361,22 +345,18 @@ public function braintree_cc_authorize( $feed, $submission_data, $form, $entry ) * @since 1.0 * @return void */ - public function authorize( $feed, $submission_data, $form, $entry ) { - - $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - - if($this->selected_payment_method=='braintree_ach'){ - return $this->ach_authorize($feed, $submission_data, $form, $entry); - } - - if( $this->selected_payment_method == 'braintree_credit_card' ) { - return $this->braintree_cc_authorize($feed, $submission_data, $form, $entry); - } - + public function authorize($feed, $submission_data, $form, $entry) { + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); + if ($this->selected_payment_method == 'braintree_ach') { + return $this->ach_authorize($feed, $submission_data, $form, $entry); + } + if ($this->selected_payment_method == 'braintree_credit_card') { + return $this->braintree_cc_authorize($feed, $submission_data, $form, $entry); + } // Prepare authorization response payload $authorization = array( 'is_authorized' => false, - 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'Your card could not be billed. Please ensure the details you entered are correct and try again.', 'gravity-forms-braintree' ) ), + 'error_message' => apply_filters('gform_braintree_credit_card_failure_message', __('Your card could not be billed. Please ensure the details you entered are correct and try again.', 'gravity-forms-braintree')), 'transaction_id' => '', 'captured_payment' => array( 'is_success' => false, @@ -385,275 +365,238 @@ public function authorize( $feed, $submission_data, $form, $entry ) { 'amount' => $submission_data['payment_amount'] ) ); - // Perform capture in this function. For this version, we won't authorize and then capture later // at least, not in this version - if( $settings = $this->get_plugin_settings() ) { - + if ($settings = $this->get_plugin_settings()) { // Sanitize card number, removing dashes and spaces - $card_number = str_replace( array( '-', ' ' ), '', $submission_data['card_number'] ); - + $card_number = str_replace(array('-', ' '), '', $submission_data['card_number']); // Prepare Braintree payload $args = array( 'amount' => $submission_data['payment_amount'], 'creditCard' => array( 'number' => $card_number, - 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), + 'expirationDate' => sprintf('%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), 'cardholderName' => $submission_data['card_name'], 'cvv' => $submission_data['card_security_code'] ) ); - $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); - try { + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + // Set to auto settlemt if applicable + if ($settings['settlement'] == 'Yes') { + $args['options']['submitForSettlement'] = 'true'; + } + // Send transaction to Braintree + $result = $gateway->transaction()->sale($args); + $this->log_debug("Braintree_Transaction::sale RESPONSE => " . print_r($result, 1)); + // Update response to reflect successful payment + if ($result->success) { + do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false, false, 'braintree'); + $authorization['is_authorized'] = true; + $authorization['error_message'] = ''; + $authorization['transaction_id'] = $result->transaction->id; + $authorization['captured_payment'] = array( + 'is_success' => true, + 'transaction_id' => $result->transaction->id, + 'amount' => $result->transaction->amount, + 'error_message' => '', + 'payment_method' => 'Credit Card' + ); + } else { + // Append gateway response text to error message if it exists. If it doesn't exist, a more hardcore + // failure has occured and it won't do the user any good to see it other than a general error message + if (isset($result->transaction->processorResponseText)) { + $authorization['error_message'] .= sprintf('. Your bank said: %s.', $result->transaction->processorResponseText); + } + } + } + } catch (Exception $e) { + // Do nothing with exception object, just fallback to generic failure + } + return $authorization; + } - $gateway = $this->getBraintreeGateway(); + return false; + } - // Set to auto settlemt if applicable - if( $settings['settlement'] == 'Yes' ) { - $args['options']['submitForSettlement'] = 'true'; - } + public function process_capture($authorization, $feed, $submission_data, $form, $entry) { - // Send transaction to Braintree - $result = $gateway->transaction()->sale($args); + do_action('gform_braintree_post_capture', rgar($authorization, 'is_authorized'), rgars($authorization, 'captured_payment/amount'), $entry, $form, $this->_args_for_deprecated_hooks['config'], $this->_args_for_deprecated_hooks['aim_response']); - $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); - // Update response to reflect successful payment - if( $result->success ) { - do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree'); - $authorization['is_authorized'] = true; - $authorization['error_message'] = ''; - $authorization['transaction_id'] = $result->transaction->id; + return parent::process_capture($authorization, $feed, $submission_data, $form, $entry); + } + /** + * Braintree Override this method to add integration code to the payment processor in order to create a subscription. + * + * This method is executed during the form validation process and allows the form submission process to fail with a + * validation error if there is anything wrong when creating the subscription. + * + * @param array $feed Current configured payment feed. + * @param array $submission_data Contains form field data submitted by the user as well as payment information + * (i.e. payment amount, setup fee, line items, etc...). + * @param array $form Current form array containing all form settings. + * @param array $entry Current entry array containing entry information (i.e data submitted by users). + * NOTE: the entry hasn't been saved to the database at this point, so this $entry + * object does not have the 'ID' property and is only a memory representation of the entry. + * + * @return array { + * Return an $subscription array + * @type bool $is_success If the subscription is successful. + * @type string $error_message The error message, if applicable. + * @type string $subscription_id The subscription ID. + * @type int $amount The subscription amount. + * @type array $captured_payment { + * If payment is captured, an additional array is created. + * @type bool $is_success If the payment capture is successful. + * @type string $error_message The error message, if any. + * @type string $transaction_id The transaction ID of the captured payment. + * @type int $amount The amount of the captured payment, if successful. + * } + * + * To implement an initial/setup fee for gateways that don't support setup fees as part of subscriptions, manually + * capture the funds for the setup fee as a separate transaction and send that payment information in the + * following 'captured_payment' array: + * + * 'captured_payment' => [ + * 'name' => 'Setup Fee', + * 'is_success' => true|false, + * 'error_message' => 'error message', + * 'transaction_id' => 'xxx', + * 'amount' => XX + * ] + * } + * @throws \Braintree\Exception\Configuration + */ + public function subscribe($feed, $submission_data, $form, $entry) { + $authorization = array( + 'is_authorized' => false, + 'is_success' => false, + 'error_message' => apply_filters('gform_braintree_credit_card_failure_message', __('Your card could not be billed. Please ensure the details you entered are correct and try again.', 'angelleye-gravity-forms-braintree')), + ); + if (empty($_POST['payment_method_nonce'])) { + return $authorization; + } + $settings = $this->get_plugin_settings(); + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + $args = array( + 'amount' => $submission_data['payment_amount'], + 'creditCard' => array( + 'number' => !empty($submission_data['card_number']) ? str_replace(array('-', ' '), '', $submission_data['card_number']) : '', + 'expirationDate' => sprintf('%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), + 'cardholderName' => $submission_data['card_name'], + 'cvv' => $submission_data['card_security_code'] + ) + ); + $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); + $customerArgs = !empty($args['customer']) ? $args['customer'] : array(); + $customer_id = $this->get_customer_id($customerArgs); + $paymentMethod = $gateway->paymentMethod()->create([ + 'customerId' => $customer_id, + 'paymentMethodNonce' => $_POST['payment_method_nonce'] + ]); + $fee_amount = !empty($submission_data['setup_fee']) ? $submission_data['setup_fee'] : 0; + $setup_fee_result = true; + if (!empty($fee_amount) && $fee_amount > 0) { + $feeArgs = array( + 'amount' => $fee_amount, + 'paymentMethodToken' => $paymentMethod->paymentMethod->token, + ); + if ($settings['settlement'] == 'Yes') { + $feeArgs['options']['submitForSettlement'] = 'true'; + } + $feeArgs = apply_filters('angelleye_braintree_parameter', $feeArgs, $submission_data, $form, $entry); + $feeResult = $gateway->transaction()->sale($feeArgs); + if ($feeResult->success) { $authorization['captured_payment'] = array( 'is_success' => true, - 'transaction_id' => $result->transaction->id, - 'amount' => $result->transaction->amount, + 'transaction_id' => $feeResult->transaction->id, + 'amount' => $feeResult->transaction->amount, 'error_message' => '', 'payment_method' => 'Credit Card' ); - + } else { + $setup_fee_result = false; + if (isset($result->transaction->processorResponseText)) { + $authorization['error_message'] .= sprintf('. Your bank said: %s.', $result->transaction->processorResponseText); + } } - else { - // Append gateway response text to error message if it exists. If it doesn't exist, a more hardcore - // failure has occured and it won't do the user any good to see it other than a general error message - if( isset( $result->transaction->processorResponseText ) ) { - $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); + } + if ($setup_fee_result) { + try { + $subscriptionArgs = array( + 'paymentMethodToken' => $paymentMethod->paymentMethod->token, + 'planId' => !empty($feed['meta']['subscriptionPlan']) ? $feed['meta']['subscriptionPlan'] : '', + 'price' => $submission_data['payment_amount'], + ); + if ($feed['meta']['recurringTimes'] == 0) { + $subscriptionArgs['neverExpires'] = true; + } else { + $subscriptionArgs['numberOfBillingCycles'] = $feed['meta']['recurringTimes']; + } + if (!empty($feed['meta']['trial_enabled'])) { + $subscriptionArgs['trialDuration'] = ''; + $subscriptionArgs['trialDurationUnit'] = ''; + $subscriptionArgs['trialPeriod'] = true; + } else { + $subscriptionArgs['firstBillingDate'] = ''; } + $subscriptionArgs = apply_filters('angelleye_gravity_braintree_subscription_args', $subscriptionArgs); + $subscription = $gateway->subscription()->create($subscriptionArgs); + if ($subscription->success) { + $authorization['is_authorized'] = true; + $authorization['is_success'] = true; + $authorization['error_message'] = ''; + $authorization['paymentMethodToken'] = $subscription->subscription->paymentMethodToken; + $authorization['subscription_id'] = $subscription->subscription->id; + $authorization['amount'] = $subscription->subscription->price; + $authorization['subscription_trial_amount'] = $subscription->subscription->price; + $authorization['subscription_start_date'] = $subscription->subscription->firstBillingDate->date; + } + } catch (Exception $e) { + } } - catch( Exception $e ) { - // Do nothing with exception object, just fallback to generic failure + } + return $authorization; + } + + /** + * Braintree override this method to add integration code to the payment processor in order to cancel a subscription. + * + * This method is executed when a subscription is canceled from the braintree Payment Gateway. + * + * @param array $entry Current entry array containing entry information (i.e data submitted by users). + * @param array $feed Current configured payment feed. + * + * @return bool Returns true if the subscription was cancelled successfully and false otherwise. + * + * @throws \Braintree\Exception\Configuration + */ + public function cancel($entry, $feed) { + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + $result = $gateway->subscription()->cancel($entry['transaction_id']); + if ($result->success) { + return true; } + } + return false; + } - return $authorization; + public function is_payment_gateway($entry_id) { + if ($this->is_payment_gateway) { + return true; } - return false; - } + $gateway = gform_get_meta($entry_id, 'payment_gateway'); - public function process_capture( $authorization, $feed, $submission_data, $form, $entry ) { - - do_action( 'gform_braintree_post_capture', rgar( $authorization, 'is_authorized' ), rgars( $authorization, 'captured_payment/amount' ), $entry, $form, $this->_args_for_deprecated_hooks['config'], $this->_args_for_deprecated_hooks['aim_response'] ); - - return parent::process_capture( $authorization, $feed, $submission_data, $form, $entry ); - } - - /** - * Braintree Override this method to add integration code to the payment processor in order to create a subscription. - * - * This method is executed during the form validation process and allows the form submission process to fail with a - * validation error if there is anything wrong when creating the subscription. - * - * @param array $feed Current configured payment feed. - * @param array $submission_data Contains form field data submitted by the user as well as payment information - * (i.e. payment amount, setup fee, line items, etc...). - * @param array $form Current form array containing all form settings. - * @param array $entry Current entry array containing entry information (i.e data submitted by users). - * NOTE: the entry hasn't been saved to the database at this point, so this $entry - * object does not have the 'ID' property and is only a memory representation of the entry. - * - * @return array { - * Return an $subscription array - * @type bool $is_success If the subscription is successful. - * @type string $error_message The error message, if applicable. - * @type string $subscription_id The subscription ID. - * @type int $amount The subscription amount. - * @type array $captured_payment { - * If payment is captured, an additional array is created. - * @type bool $is_success If the payment capture is successful. - * @type string $error_message The error message, if any. - * @type string $transaction_id The transaction ID of the captured payment. - * @type int $amount The amount of the captured payment, if successful. - * } - * - * To implement an initial/setup fee for gateways that don't support setup fees as part of subscriptions, manually - * capture the funds for the setup fee as a separate transaction and send that payment information in the - * following 'captured_payment' array: - * - * 'captured_payment' => [ - * 'name' => 'Setup Fee', - * 'is_success' => true|false, - * 'error_message' => 'error message', - * 'transaction_id' => 'xxx', - * 'amount' => XX - * ] - * } - * @throws \Braintree\Exception\Configuration - */ - public function subscribe( $feed, $submission_data, $form, $entry ) { - - $authorization = array( - 'is_authorized' => false, - 'is_success' => false, - 'error_message' => apply_filters( 'gform_braintree_credit_card_failure_message', __( 'Your card could not be billed. Please ensure the details you entered are correct and try again.', 'angelleye-gravity-forms-braintree' ) ), - ); - - if(empty($_POST['payment_method_nonce'])) { - return $authorization; - } - - $settings = $this->get_plugin_settings(); - $gateway = $this->getBraintreeGateway(); - - $args = array( - 'amount' => $submission_data['payment_amount'], - 'creditCard' => array( - 'number' => !empty($submission_data['card_number']) ? str_replace( array( '-', ' ' ), '', $submission_data['card_number'] ) : '', - 'expirationDate' => sprintf( '%s/%s', $submission_data['card_expiration_date'][0], $submission_data['card_expiration_date'][1]), - 'cardholderName' => $submission_data['card_name'], - 'cvv' => $submission_data['card_security_code'] - ) - ); - - $args = apply_filters('angelleye_braintree_parameter', $args, $submission_data, $form, $entry); - - $customerArgs = !empty($args['customer']) ? $args['customer'] : array(); - - $customer_id = $this->get_customer_id($customerArgs); - - $paymentMethod = $gateway->paymentMethod()->create([ - 'customerId' => $customer_id, - 'paymentMethodNonce' => $_POST['payment_method_nonce'] - ]); - - $fee_amount = !empty($submission_data['setup_fee']) ? $submission_data['setup_fee'] : 0; - $setup_fee_result = true; - - if ( ! empty( $fee_amount ) && $fee_amount > 0 ) { - - $feeArgs = array( - 'amount' => $fee_amount, - 'paymentMethodToken' => $paymentMethod->paymentMethod->token, - ); - - if( $settings['settlement'] == 'Yes' ) { - $feeArgs['options']['submitForSettlement'] = 'true'; - } - - $feeArgs = apply_filters('angelleye_braintree_parameter', $feeArgs, $submission_data, $form, $entry); - - $feeResult = $gateway->transaction()->sale($feeArgs); - - if( $feeResult->success ) { - $authorization['captured_payment'] = array( - 'is_success' => true, - 'transaction_id' => $feeResult->transaction->id, - 'amount' => $feeResult->transaction->amount, - 'error_message' => '', - 'payment_method' => 'Credit Card' - ); - } else { - $setup_fee_result = false; - if( isset( $result->transaction->processorResponseText ) ) { - $authorization['error_message'] .= sprintf( '. Your bank said: %s.', $result->transaction->processorResponseText); - } - } - } - - if( $setup_fee_result ) { - - try { - $subscriptionArgs = array( - 'paymentMethodToken' => $paymentMethod->paymentMethod->token, - 'planId' => !empty($feed['meta']['subscriptionPlan']) ? $feed['meta']['subscriptionPlan'] : '', - 'price' => $submission_data['payment_amount'], - ); - - if ( $feed['meta']['recurringTimes'] == 0 ) { - $subscriptionArgs['neverExpires'] = true; - } else { - $subscriptionArgs['numberOfBillingCycles'] = $feed['meta']['recurringTimes']; - } - - if ( !empty($feed['meta']['trial_enabled']) ) { - $subscriptionArgs['trialDuration'] = ''; - $subscriptionArgs['trialDurationUnit'] = ''; - $subscriptionArgs['trialPeriod'] = true; - } else { - $subscriptionArgs['firstBillingDate'] = ''; - } - - $subscriptionArgs = apply_filters( 'angelleye_gravity_braintree_subscription_args', $subscriptionArgs ); - $subscription = $gateway->subscription()->create($subscriptionArgs); - - if($subscription->success) { - - $authorization['is_authorized'] = true; - $authorization['is_success'] = true; - $authorization['error_message'] = ''; - $authorization['paymentMethodToken'] = $subscription->subscription->paymentMethodToken; - $authorization['subscription_id'] = $subscription->subscription->id; - $authorization['amount'] = $subscription->subscription->price; - $authorization['subscription_trial_amount'] = $subscription->subscription->price; - $authorization['subscription_start_date'] = $subscription->subscription->firstBillingDate->date; - } - - } catch ( Exception $e ) { - - } - } - - return $authorization; - } - - /** - * Braintree override this method to add integration code to the payment processor in order to cancel a subscription. - * - * This method is executed when a subscription is canceled from the braintree Payment Gateway. - * - * @param array $entry Current entry array containing entry information (i.e data submitted by users). - * @param array $feed Current configured payment feed. - * - * @return bool Returns true if the subscription was cancelled successfully and false otherwise. - * - * @throws \Braintree\Exception\Configuration - */ - public function cancel( $entry, $feed ) { - - $gateway = $this->getBraintreeGateway(); - - $result = $gateway->subscription()->cancel($entry['transaction_id']); - - if($result->success) { - return true; - } - - return false; - } - - public function is_payment_gateway( $entry_id ) { - - if ( $this->is_payment_gateway ) { - return true; - } - - $gateway = gform_get_meta( $entry_id, 'payment_gateway' ); - - return in_array( $gateway, array( 'Braintree', $this->_slug ) ); - } + return in_array($gateway, array('Braintree', $this->_slug)); + } /** * Create and display feed settings fields. @@ -661,113 +604,112 @@ public function is_payment_gateway( $entry_id ) { * @since 1.0 * @return void */ - public function feed_settings_fields () { + public function feed_settings_fields() { // Get defaults from GFPaymentAddOn $settings = parent::feed_settings_fields(); // Remove billing information - $settings = $this->remove_field( 'billingInformation', $settings ); + $settings = $this->remove_field('billingInformation', $settings); // Remove options - $settings = $this->remove_field( 'options', $settings ); + $settings = $this->remove_field('options', $settings); // Remove the subscription option from transaction type dropdown - $transaction_type = $this->get_field( 'transactionType', $settings ); + $transaction_type = $this->get_field('transactionType', $settings); //foreach( $transaction_type['choices'] as $index => $choice ) { - //if( $choice['value'] == 'subscription' ) { - //unset( $transaction_type['choices'][$index] ); - //} + //if( $choice['value'] == 'subscription' ) { + //unset( $transaction_type['choices'][$index] ); //} - - $transactionType = ''; - foreach( $settings as $index => $setting ) { - if( !empty($setting['dependency']['field']) && $setting['dependency']['field'] == 'transactionType' ) { - $transactionType = !empty($setting['dependency']['values'][0]) ? $setting['dependency']['values'][0] :''; - } - } - - if( (!empty($_POST['_gaddon_setting_transactionType']) && $_POST['_gaddon_setting_transactionType'] == 'subscription') || ( empty($_POST['_gaddon_setting_transactionType']) && !empty($transactionType) && $transactionType == 'subscription') ) { - $form_page_link = add_query_arg([ - 'id' => !empty($_REQUEST['id']) ? $_REQUEST['id'] : '', - ], menu_page_url('gf_edit_forms', false)); - $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.','angelleye-gravity-forms-braintree'), '',''); - } - - $settings = $this->replace_field( 'transactionType', $transaction_type, $settings ); - - $settings = parent::remove_field( 'trial', $settings ); - - $createBraintreePlanUrl = $this->merchant_url('plans/new'); - $api_settings_field = array( - array( - 'name' => 'braintree_trial', - 'label' => esc_html__( 'Trial', 'angelleye-gravity-forms-braintree' ), - 'type' => 'braintree_trial', - 'hidden' => '', - 'tooltip' => '' - ), - array( - 'name' => 'subscriptionPlan', - 'label' => esc_html__( 'Plan', 'angelleye-gravity-forms-braintree' ), - 'type' => 'select', - 'choices' => $this->get_plans(), - 'required' => true, - 'tooltip' => sprintf(__('Plugin will fetch and display the subscription plans. Create the %splan%s in your Braintree account.','angelleye-gravity-forms-braintree'),'',''), - ), - ); - - $settings = $this->add_field_after( 'setupFee', $api_settings_field, $settings ); + //} + + $transactionType = ''; + foreach ($settings as $index => $setting) { + if (!empty($setting['dependency']['field']) && $setting['dependency']['field'] == 'transactionType') { + $transactionType = !empty($setting['dependency']['values'][0]) ? $setting['dependency']['values'][0] : ''; + } + } + + if ((!empty($_POST['_gaddon_setting_transactionType']) && $_POST['_gaddon_setting_transactionType'] == 'subscription') || ( empty($_POST['_gaddon_setting_transactionType']) && !empty($transactionType) && $transactionType == 'subscription')) { + $form_page_link = add_query_arg([ + 'id' => !empty($_REQUEST['id']) ? $_REQUEST['id'] : '', + ], menu_page_url('gf_edit_forms', false)); + $transaction_type['description'] = sprintf(__('When building your subscription form, make sure to use the %sBraintree CC%s field instead of the basic Credit Card field.', 'angelleye-gravity-forms-braintree'), '', ''); + } + + $settings = $this->replace_field('transactionType', $transaction_type, $settings); + + $settings = parent::remove_field('trial', $settings); + + $createBraintreePlanUrl = $this->merchant_url('plans/new'); + $api_settings_field = array( + array( + 'name' => 'braintree_trial', + 'label' => esc_html__('Trial', 'angelleye-gravity-forms-braintree'), + 'type' => 'braintree_trial', + 'hidden' => '', + 'tooltip' => '' + ), + array( + 'name' => 'subscriptionPlan', + 'label' => esc_html__('Plan', 'angelleye-gravity-forms-braintree'), + 'type' => 'select', + 'choices' => $this->get_plans(), + 'required' => true, + 'tooltip' => sprintf(__('Plugin will fetch and display the subscription plans. Create the %splan%s in your Braintree account.', 'angelleye-gravity-forms-braintree'), '', ''), + ), + ); + + $settings = $this->add_field_after('setupFee', $api_settings_field, $settings); // Return sanitized settings return $settings; - } - public function merchant_url( $tab = 'plans') { + public function merchant_url($tab = 'plans') { - $settings = $this->get_plugin_settings(); + $settings = $this->get_plugin_settings(); - $braintreeUrl = '#'; - if( !empty($settings['merchant-id']) ) { - $environment = ! empty( $settings['environment'] ) ? strtolower( $settings['environment'] ) : 'sandbox'; - $environmentUrl = ( $environment == 'sandbox' ) ? 'sandbox.' : ''; + $braintreeUrl = '#'; + if (!empty($settings['merchant-id'])) { + $environment = !empty($settings['environment']) ? strtolower($settings['environment']) : 'sandbox'; + $environmentUrl = ( $environment == 'sandbox' ) ? 'sandbox.' : ''; - $braintree_config = new \Braintree\Configuration( [ - 'environment' => strtolower( $settings['environment'] ), - 'merchantId' => $settings['merchant-id'], - 'publicKey' => $settings['public-key'], - 'privateKey' => $settings['private-key'] - ] ); + $braintree_config = new \Braintree\Configuration([ + 'environment' => strtolower($settings['environment']), + 'merchantId' => $settings['merchant-id'], + 'publicKey' => $settings['public-key'], + 'privateKey' => $settings['private-key'] + ]); - $merchantPath = $braintree_config->merchantPath(); - $braintreeUrl = "https://{$environmentUrl}braintreegateway.com{$merchantPath}/{$tab}"; - } + $merchantPath = $braintree_config->merchantPath(); + $braintreeUrl = "https://{$environmentUrl}braintreegateway.com{$merchantPath}/{$tab}"; + } - return $braintreeUrl; + return $braintreeUrl; } - /** - * This function is callback for braintree_trial setting field. - * - * @param array $field Settings fields - * @param bool $echo Display or return - * - * @return string $html - * - * @throws \Braintree\Exception\Configuration - */ - public function settings_braintree_trial( $field, $echo = true ) { - - $braintreePlans = $this->merchant_url(); - $html = sprintf(__( 'Select your product trial form %sBraintree Plans%s', 'angelleye-gravity-forms-braintree' ),'', ''); - - if ( $echo ) { - echo $html; - } - - return $html; + /** + * This function is callback for braintree_trial setting field. + * + * @param array $field Settings fields + * @param bool $echo Display or return + * + * @return string $html + * + * @throws \Braintree\Exception\Configuration + */ + public function settings_braintree_trial($field, $echo = true) { + + $braintreePlans = $this->merchant_url(); + $html = sprintf(__('Select your product trial form %sBraintree Plans%s', 'angelleye-gravity-forms-braintree'), '', ''); + + if ($echo) { + echo $html; + } + + return $html; } /** @@ -776,7 +718,7 @@ public function settings_braintree_trial( $field, $echo = true ) { * @since 1.0 * @return void */ - public function plugin_settings_fields () { + public function plugin_settings_fields() { return array( array( @@ -805,25 +747,25 @@ public function plugin_settings_fields () { ) ) ), - array( - 'title' => 'Braintree ACH Settings', - 'fields' => array( - array( - 'name' => 'tokenization-key', - 'tooltip' => 'Your Braintree Tokenization Key', - 'label' => 'Tokenization Key', - 'type' => 'text', - 'class' => 'medium' - ), - array( - 'name' => 'business-name', - 'tooltip' => 'For all ACH transactions, you are required to collect a mandate or “proof of authorization” from the customer to prove that you have their explicit permission to debit their bank account. We will put your business name in authorization text', - 'label' => 'Business name', - 'type' => 'text', - 'class' => 'medium' - ) - ) - ), + array( + 'title' => 'Braintree ACH Settings', + 'fields' => array( + array( + 'name' => 'tokenization-key', + 'tooltip' => 'Your Braintree Tokenization Key', + 'label' => 'Tokenization Key', + 'type' => 'text', + 'class' => 'medium' + ), + array( + 'name' => 'business-name', + 'tooltip' => 'For all ACH transactions, you are required to collect a mandate or “proof of authorization” from the customer to prove that you have their explicit permission to debit their bank account. We will put your business name in authorization text', + 'label' => 'Business name', + 'type' => 'text', + 'class' => 'medium' + ) + ) + ), array( 'title' => 'Payment Settings', 'fields' => array( @@ -866,9 +808,7 @@ public function plugin_settings_fields () { ) ) ) - ); - } /** @@ -878,11 +818,11 @@ public function plugin_settings_fields () { * @since 1.0 * @return void */ - public function settings_are_valid ( $settings ) { - if( empty( $settings ) ) { + public function settings_are_valid($settings) { + if (empty($settings)) { return false; } - if(!empty($settings['merchant-id']) && !empty($settings['public-key']) && !empty($settings['public-key'])) { + if (!empty($settings['merchant-id']) && !empty($settings['public-key']) && !empty($settings['public-key'])) { return true; } else { return false; @@ -895,16 +835,15 @@ public function settings_are_valid ( $settings ) { * @since 1.0 * @return void */ - public function get_plugin_settings () { + public function get_plugin_settings() { $settings = parent::get_plugin_settings(); - if( $this->settings_are_valid( $settings ) ) { + if ($this->settings_are_valid($settings)) { return $settings; } else { return false; } - } public function angelleye_gform_braintree_display_push_notification() { @@ -912,7 +851,7 @@ public function angelleye_gform_braintree_display_push_notification() { $user_id = $current_user->ID; if (false === ( $response = get_transient('angelleye_gravity_braintree_push_notification_result') )) { $response = $this->angelleye_get_push_notifications(); - if(is_object($response)) { + if (is_object($response)) { set_transient('angelleye_gravity_braintree_push_notification_result', $response, 12 * HOUR_IN_SECONDS); } } @@ -954,19 +893,19 @@ public function angelleye_get_push_notifications() { } public function angelleye_display_push_notification($response_data) { - echo ''; + echo ''; } public function angelleye_gform_braintree_adismiss_notice() { @@ -978,181 +917,179 @@ public function angelleye_gform_braintree_adismiss_notice() { } } - public function include_angelleye_braintree_style_noconflict( $styles ) { - $styles[] = 'gravity-forms-braintree-admin-css'; - return $styles; + public function include_angelleye_braintree_style_noconflict($styles) { + $styles[] = 'gravity-forms-braintree-admin-css'; + return $styles; } - public function include_angelleye_braintree_script_noconflict( $scripts ) { - $scripts[] = 'gravity-forms-braintree-admin'; - return $scripts; + public function include_angelleye_braintree_script_noconflict($scripts) { + $scripts[] = 'gravity-forms-braintree-admin'; + return $scripts; } public function enqueue_scripts_js() { - if(GFForms::is_gravity_page()) { - wp_enqueue_script( 'gravity-forms-braintree-admin', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/gravity-forms-braintree-admin.js', array( 'jquery' ), $this->_version, false ); - } + if (GFForms::is_gravity_page()) { + wp_enqueue_script('gravity-forms-braintree-admin', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/gravity-forms-braintree-admin.js', array('jquery'), $this->_version, false); + } } public function enqueue_styles_css() { - if(GFForms::is_gravity_page()) { - wp_enqueue_style( 'gravity-forms-braintree-admin-css', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/css/gravity-forms-braintree-admin.css', array(), $this->_version, 'all' ); - } + if (GFForms::is_gravity_page()) { + wp_enqueue_style('gravity-forms-braintree-admin-css', GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/css/gravity-forms-braintree-admin.css', array(), $this->_version, 'all'); + } } - /** - * Load the Braintree JS and Custom JS in frontend - * @return array - */ - public function scripts() { - $translation_array = []; - $settings = $this->get_plugin_settings(); - if($settings!==false){ - $translation_array['ach_bt_token'] = @$settings['tokenization-key']; - $translation_array['ach_business_name'] = @$settings['business-name']; - } - - $scripts = array( - array( - 'handle' => 'angelleye-gravity-form-braintree-client', - 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/client.min.js', - 'version' => $this->_version, - 'deps' => array( 'jquery' ), - 'in_footer' => false, - 'callback' => array( $this, 'localize_scripts' ), - 'enqueue' => array( - array( 'field_types' => array( 'braintree_ach' ) ) - ) - ), - array( - 'handle' => 'angelleye-gravity-form-braintree-data-collector', - 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/data-collector.min.js', - 'version' => $this->_version, - 'deps' => array( ), - 'in_footer' => false, - 'callback' => array( $this, 'localize_scripts' ), - 'enqueue' => array( - array( 'field_types' => array( 'braintree_ach' ) ) - ) - ), - array( - 'handle' => 'angelleye-gravity-form-braintree-usbankaccount', - 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/us-bank-account.min.js', - 'version' => $this->_version, - 'deps' => array( ), - 'in_footer' => false, - 'callback' => array( $this, 'localize_scripts' ), - 'enqueue' => array( - array( 'field_types' => array( 'braintree_ach' ) ) - ) - ), - array( - 'handle' => 'angelleye_gravity_form_braintree_ach_handler', - 'src' => GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/angelleye-braintree-ach-cc.js', - 'version' => $this->_version, - 'deps' => array( 'jquery', 'angelleye-gravity-form-braintree-client', 'angelleye-gravity-form-braintree-data-collector', - 'angelleye-gravity-form-braintree-usbankaccount'), - 'in_footer' => false, - 'callback' => array( $this, 'localize_scripts' ), - 'strings' => $translation_array, - 'enqueue' => array( + /** + * Load the Braintree JS and Custom JS in frontend + * @return array + */ + public function scripts() { + $translation_array = []; + $settings = $this->get_plugin_settings(); + if ($settings !== false) { + $translation_array['ach_bt_token'] = @$settings['tokenization-key']; + $translation_array['ach_business_name'] = @$settings['business-name']; + } + + $scripts = array( + array( + 'handle' => 'angelleye-gravity-form-braintree-client', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/client.min.js', + 'version' => $this->_version, + 'deps' => array('jquery'), + 'in_footer' => false, + 'callback' => array($this, 'localize_scripts'), + 'enqueue' => array( + array('field_types' => array('braintree_ach')) + ) + ), + array( + 'handle' => 'angelleye-gravity-form-braintree-data-collector', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/data-collector.min.js', + 'version' => $this->_version, + 'deps' => array(), + 'in_footer' => false, + 'callback' => array($this, 'localize_scripts'), + 'enqueue' => array( + array('field_types' => array('braintree_ach')) + ) + ), + array( + 'handle' => 'angelleye-gravity-form-braintree-usbankaccount', + 'src' => 'https://js.braintreegateway.com/web/3.61.0/js/us-bank-account.min.js', + 'version' => $this->_version, + 'deps' => array(), + 'in_footer' => false, + 'callback' => array($this, 'localize_scripts'), + 'enqueue' => array( + array('field_types' => array('braintree_ach')) + ) + ), + array( + 'handle' => 'angelleye_gravity_form_braintree_ach_handler', + 'src' => GRAVITY_FORMS_BRAINTREE_ASSET_URL . 'assets/js/angelleye-braintree-ach-cc.js', + 'version' => $this->_version, + 'deps' => array('jquery', 'angelleye-gravity-form-braintree-client', 'angelleye-gravity-form-braintree-data-collector', + 'angelleye-gravity-form-braintree-usbankaccount'), + 'in_footer' => false, + 'callback' => array($this, 'localize_scripts'), + 'strings' => $translation_array, + 'enqueue' => array( // array( // 'admin_page' => array( 'form_settings' ), // 'tab' => 'simpleaddon' // ) - array( 'field_types' => array( 'braintree_ach' ) ) - ) - ), - ); - - return array_merge( parent::scripts(), $scripts ); - } - - /** - * Override default billing cycles intervals for subscription plan. - * - * @return array $billing_cycles - */ - public function supported_billing_intervals() { - $billing_cycles = array( - 'month' => array( 'label' => esc_html__( 'month(s)', 'angelleye-gravity-forms-braintree' ), 'min' => 1, 'max' => 24 ) - ); - - return $billing_cycles; - } - - /** - * Get all Braintree plans using Braintree payment Gateway settings. - * - * @return array $plans - * - * @throws \Braintree\Exception\Configuration - */ - public function get_plans() { - - $gateway = $this->getBraintreeGateway(); - $plan_lists = $gateway->plan()->all(); - - $plans = array( array( - 'label' => __('Select a plan','angelleye-gravity-forms-braintree'), - 'value' => '', - )); - - if( !empty($plan_lists)) { - foreach ($plan_lists as $plan ) { - $plans[] = array( - 'label' => $plan->name, - 'value' => $plan->id, - ); - } - } - - return $plans; - } - - /** - * Get customer id using customer email address. - * - * If customer email address already exists in braintree customer lists then provide customer id, - * Otherwise create a new customer using customer details and then provide a customer id. - * - * @param array $args - * - * @return int|string $customer_id Customer id. - * - * @throws \Braintree\Exception\Configuration - */ - public function get_customer_id( $args ) { - - //check if customer detail is empty or not array then return. - if(empty($args) || !is_array($args)) { - return ''; - } - - $email = !empty($args['email']) ? $args['email'] : ''; - - $gateway = $this->getBraintreeGateway(); - - //search customer using email address - $collections = $gateway->customer()->search([ - Braintree\CustomerSearch::email()->is($email) - ]); - - $customer_id = 0; - foreach ($collections as $key => $collection) { - if( !empty($collection->id) ) { - $customer_id = $collection->id; - } - } - - //check $customer_id is empty then create a new customer. - if(empty($customer_id)) { - $customer = $gateway->customer()->create( $args ); - if(!empty($customer->customer->id)) { - $customer_id = $customer->customer->id; - } - } - - return $customer_id; - } -} \ No newline at end of file + array('field_types' => array('braintree_ach')) + ) + ), + ); + + return array_merge(parent::scripts(), $scripts); + } + + /** + * Override default billing cycles intervals for subscription plan. + * + * @return array $billing_cycles + */ + public function supported_billing_intervals() { + $billing_cycles = array( + 'month' => array('label' => esc_html__('month(s)', 'angelleye-gravity-forms-braintree'), 'min' => 1, 'max' => 24) + ); + + return $billing_cycles; + } + + /** + * Get all Braintree plans using Braintree payment Gateway settings. + * + * @return array $plans + * + * @throws \Braintree\Exception\Configuration + */ + public function get_plans() { + try { + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + $plan_lists = $gateway->plan()->all(); + $plans = array(array( + 'label' => __('Select a plan', 'angelleye-gravity-forms-braintree'), + 'value' => '', + )); + if (!empty($plan_lists)) { + foreach ($plan_lists as $plan) { + $plans[] = array( + 'label' => $plan->name, + 'value' => $plan->id, + ); + } + } + return $plans; + } + } catch (Exception $ex) { + + } + } + + /** + * Get customer id using customer email address. + * + * If customer email address already exists in braintree customer lists then provide customer id, + * Otherwise create a new customer using customer details and then provide a customer id. + * + * @param array $args + * + * @return int|string $customer_id Customer id. + * + * @throws \Braintree\Exception\Configuration + */ + public function get_customer_id($args) { + //check if customer detail is empty or not array then return. + if (empty($args) || !is_array($args)) { + return ''; + } + $email = !empty($args['email']) ? $args['email'] : ''; + $gateway = $this->getBraintreeGateway(); + if ($gateway) { + //search customer using email address + $collections = $gateway->customer()->search([ + Braintree\CustomerSearch::email()->is($email) + ]); + $customer_id = 0; + foreach ($collections as $key => $collection) { + if (!empty($collection->id)) { + $customer_id = $collection->id; + } + } + //check $customer_id is empty then create a new customer. + if (empty($customer_id)) { + $customer = $gateway->customer()->create($args); + if (!empty($customer->customer->id)) { + $customer_id = $customer->customer->id; + } + } + return $customer_id; + } + } + +} From 9a9e770ed9600e912c5000660b7c48d4d13fb256 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 17 Jan 2022 15:56:51 +0530 Subject: [PATCH 93/99] Updates changelog and version for v4.0.4 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 39c10d3..b1231f2 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0.3 + * Version: 4.0.4 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0.3'; + public static $version = '4.0.4'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 37fd740..49411a7 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0.3'; + protected $_version = '4.0.4'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; protected $_path = 'gravity-forms-braintree/lib/class.plugify-gform-braintree.php'; diff --git a/readme.txt b/readme.txt index e293b8c..754b4d8 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 Tested up to: 5.8.3 -Stable tag: 4.0.3 +Stable tag: 4.0.4 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.4 - 01.17.2022 = +* Fix - Resolved PHP Fatal error. ([GFB-41](https://github.com/angelleye/gravity-forms-braintree/pull/38)) + = 4.0.3 - 01.10.2022 = * Fix - Resolved PHP Fatal error. ([GFB-37](https://github.com/angelleye/gravity-forms-braintree/pull/37)) From f0094ced3ea7d5b48a3022dc9e2df55c5a91c4fc Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 21 Jan 2022 16:12:52 +0530 Subject: [PATCH 94/99] ACH Form Error, GFB-42 --- assets/js/angelleye-braintree-ach-cc.js | 124 ++- ...-angelleye-gravity-braintree-ach-field.php | 849 +++++++++--------- 2 files changed, 524 insertions(+), 449 deletions(-) diff --git a/assets/js/angelleye-braintree-ach-cc.js b/assets/js/angelleye-braintree-ach-cc.js index 8af37b0..29efbe3 100644 --- a/assets/js/angelleye-braintree-ach-cc.js +++ b/assets/js/angelleye-braintree-ach-cc.js @@ -1,5 +1,5 @@ jQuery(document).ready(function ($) { - if($('.gform_payment_method_options').length){ + if ($('.gform_payment_method_options').length) { var payment_methods = {}; $('.gform_payment_method_options input[type=radio]').each(function () { var targetdiv = $(this).attr('targetdiv'); @@ -7,19 +7,19 @@ jQuery(document).ready(function ($) { payment_methods[value] = targetdiv; }); - $('.gform_payment_method_options').on('click','input[type=radio]', function () { + $('.gform_payment_method_options').on('click', 'input[type=radio]', function () { var selectedradio = $(this).val(); for (var i in payment_methods) - if(i!==selectedradio) - $(this).closest('form').find('#'+payment_methods[i]).slideUp() + if (i !== selectedradio) + $(this).closest('form').find('#' + payment_methods[i]).slideUp() var targetdiv = $(this).attr('targetdiv'); - $(this).closest('form').find('#'+targetdiv).slideDown(); + $(this).closest('form').find('#' + targetdiv).slideDown(); }); var selectedradio = $('.gform_payment_method_options input[type=radio]:checked').val(); - switch(selectedradio){ + switch (selectedradio) { case 'braintree_ach': $('.gform_payment_method_options input[value=braintree_ach]').trigger('click'); break; @@ -33,16 +33,17 @@ jQuery(document).ready(function ($) { $('.custom_ach_form_submit_btn').click(function (e) { + window[ 'gf_submitting_' + $("input[name='gform_submit']").val() ] = true; + $('#gform_ajax_spinner_' + $("input[name='gform_submit']").val()).remove(); e.preventDefault(); - var curlabel = $(this).html(); var form = $(this).closest('form'); var selectedradio = form.find('.gform_payment_method_options input[type=radio]:checked').val(); var check_if_ach_form = form.find('.ginput_ach_form_container'); - if(check_if_ach_form.length && (selectedradio === 'braintree_ach' || check_if_ach_form.closest('.gfield').css('display')!=='none')){ - if(form.find('.ginput_container_address').length==0){ + if (check_if_ach_form.length && (selectedradio === 'braintree_ach' || check_if_ach_form.closest('.gfield').css('display') !== 'none')) { + if (form.find('.ginput_container_address').length == 0) { alert('ACH payment requires billing address fields, so please include Billing Address field in your Gravity form.'); return; } @@ -56,67 +57,71 @@ jQuery(document).ready(function ($) { var streetAddress = form.find('.ginput_container_address .address_line_1 input[type=text]').val(); var extendedAddress = form.find('.ginput_container_address .address_line_2 input[type=text]').val(); var locality = form.find('.ginput_container_address .address_city input[type=text]').val(); - var region = form.find('.ginput_container_address .address_state input[type=text]').val(); + var region = form.find('.ginput_container_address .address_state input[type=text], .ginput_container_address .address_state select').val(); var postalCode = form.find('.ginput_container_address .address_zip input[type=text]').val(); + if (region.length > 2) { + region = stateNameToAbbreviation(region); + } + var address_validation_errors = []; - if(streetAddress==''){ + if (streetAddress == '') { address_validation_errors.push('Please enter a street address.'); } - if(locality==''){ + if (locality == '') { address_validation_errors.push('Please enter your city.'); } - if(region==''){ + if (region == '') { address_validation_errors.push('Please enter your state.'); } - if(postalCode==''){ + if (postalCode == '') { address_validation_errors.push('Please enter your postal code.'); } - if(address_validation_errors.length){ + if (address_validation_errors.length) { alert(address_validation_errors.join('\n')); return; } var achform_validation_errors = []; - if(routing_number=='' || isNaN(routing_number) || account_number=='' || isNaN(account_number)){ + if (routing_number == '' || isNaN(routing_number) || account_number == '' || isNaN(account_number)) { achform_validation_errors.push('Please enter a valid routing and account number.') } - if(account_type==''){ + if (account_type == '') { achform_validation_errors.push('Please select your account type.') } - if(account_holdername==''){ + if (account_holdername == '') { achform_validation_errors.push('Please enter the account holder name.'); - }else { + } else { var account_holder_namebreak = account_holdername.split(' '); if (account_type == 'S' && account_holder_namebreak.length < 2) { achform_validation_errors.push('Please enter the account holder first and last name.'); } } - if(account_number !== account_number_verification){ + if (account_number !== account_number_verification) { achform_validation_errors.push('Account Number and Account Number Verification field should be same.'); } - if(achform_validation_errors.length){ + if (achform_validation_errors.length) { alert(achform_validation_errors.join('\n')); return; } var submitbtn = $(this); - submitbtn.attr('disabled', true).html('Please wait...').css('opacity', '0.4'); + // submitbtn.attr('disabled', true).html('Please wait...').css('opacity', '0.4'); braintree.client.create({ authorization: angelleye_gravity_form_braintree_ach_handler_strings.ach_bt_token }, function (clientErr, clientInstance) { if (clientErr) { alert('There was an error creating the Client, Please check your Braintree Settings.'); - console.error('clientErr',clientErr); + console.error('clientErr', clientErr); return; } @@ -127,7 +132,7 @@ jQuery(document).ready(function ($) { if (err) { alert('We are unable to validate your system, please try again.'); resetButtonLoading(submitbtn, curlabel); - console.error('dataCollectorError',err); + console.error('dataCollectorError', err); return; } @@ -139,7 +144,7 @@ jQuery(document).ready(function ($) { if (usBankAccountErr) { alert('There was an error initiating the bank request. Please try again.'); resetButtonLoading(submitbtn, curlabel); - console.error('usBankAccountErr',usBankAccountErr); + console.error('usBankAccountErr', usBankAccountErr); return; } @@ -184,18 +189,83 @@ jQuery(document).ready(function ($) { form.append(""); form.append(''); + + form.submit(); }); }); }); }); - }else { + } else { form.submit(); } }); }); +function stateNameToAbbreviation(name) { + let states = { + "Alabama": "AL", + "Alaska": "AK", + "Arizona": "AZ", + "Arkansas": "AR", + "California": "CA", + "Colorado": "CO", + "Connecticut": "CT", + "Delaware": "DE", + "District of Columbia": "DC", + "Florida": "FL", + "Georgia": "GA", + "Hawaii": "HI", + "Idaho": "ID", + "Illinois": "IL", + "Indiana": "IN", + "Iowa": "IA", + "Kansas": "KS", + "Kentucky": "KY", + "Louisiana": "LA", + "Maine": "ME", + "Maryland": "MD", + "Massachusetts": "MA", + "Michigan": "MI", + "Minnesota": "MN", + "Mississippi": "MS", + "Missouri": "MO", + "Montana": "MT", + "Nebraska": "NE", + "Nevada": "NV", + "New Hampshire": "NH", + "New Jersey": "NJ", + "New Mexico": "NM", + "New York": "NY", + "North Carolina": "NC", + "North Dakota": "ND", + "Ohio": "OH", + "Oklahoma": "OK", + "Oregon": "OR", + "Pennsylvania": "PA", + "Rhode Island": "RI", + "South Carolina": "SC", + "South Dakota": "SD", + "Tennessee": "TN", + "Texas": "TX", + "Utah": "UT", + "Vermont": "VT", + "Virginia": "VA", + "Washington": "WA", + "West Virginia": "WV", + "Wisconsin": "WI", + "Wyoming": "WY", + "Armed Forces Americas": "AA", + "Armed Forces Europe": "AE", + "Armed Forces Pacific": "AP" + } + if (states[name] !== null) { + return states[name]; + } + return name; +} + function resetButtonLoading(submitbtn, curlabel) { - submitbtn.attr('disabled', false).html(curlabel).css('opacity', '1'); + // submitbtn.attr('disabled', false).html(curlabel).css('opacity', '1'); } diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index 1c1c200..9ba9d5c 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -4,470 +4,475 @@ class Angelleye_Gravity_Braintree_ACH_Field extends GF_Field { - private $selected_payment_method = ''; - /** - * @var string $type The field type. - */ - public $type = 'braintree_ach'; - - /** - * Return the field title, for use in the form editor. - * - * @return string - */ - public function get_form_editor_field_title() { - return __( 'ACH Form', 'gravity-forms-braintree' ); - } - - /** - * Assign the field button to the Pricing Fields group. - * - * @return array - */ - public function get_form_editor_button() { - return [ 'group' => 'pricing_fields', 'text' => 'ACH Form' ]; - } - - /** - * The settings which should be available on the field in the form editor. - * - * @return array - */ - function get_form_editor_field_settings() { - return ['label_setting', 'label_placement_setting', 'admin_label_setting', 'description_setting', 'sub_labels_setting', - 'sub_label_placement_setting', 'error_message_setting', 'css_class_setting', 'conditional_logic_field_setting', - 'force_ssl_field_setting', 'rules_setting', 'input_placeholders_setting', - ]; - } - - /** - * Enable this field for use with conditional logic. - * - * @return bool - */ - public function is_conditional_logic_supported() { - return true; - } - - /** - * The scripts to be included in the form editor. - * - * @return string - */ - public function get_form_editor_inline_script_on_page_render() { - - } - - /** - * Override default button for the ACH Payments - * @param $button - * @param $form - * - * @return string - */ - function overrideSubmitButton( $button, $form ) { - return ""; - } - - /** - * Returns the fields input for backend and frontend - * @param array $form - * @param string $value - * @param null $entry - * - * @return string - */ - public function get_field_input( $form, $value = '', $entry = null ) { - add_filter( 'gform_submit_button', [$this, 'overrideSubmitButton'], 10, 2 ); - $is_entry_detail = $this->is_entry_detail(); - $is_form_editor = $this->is_form_editor(); - - $form_id = $form['id']; - $id = intval( $this->id ); - $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; - $form_id = ( $is_entry_detail || $is_form_editor ) && empty( $form_id ) ? rgget( 'id' ) : $form_id; - - $disabled_text = $is_form_editor ? "disabled='disabled'" : ''; - $class_suffix = $is_entry_detail ? '_admin' : ''; - - $sub_label_placement = rgar( $form, 'subLabelPlacement' ); - $field_sub_label_placement = $this->subLabelPlacement; - $is_sub_label_above = $field_sub_label_placement == 'above' || ( empty( $field_sub_label_placement ) && $sub_label_placement == 'above' ); - $sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : ''; - - $account_number = ''; - $routing_number = ''; - $account_type = ''; - $account_holder_name = ''; - $autocomplete = RGFormsModel::is_html5_enabled() ? "autocomplete='off'" : ''; - - if ( is_array( $value ) ) { - $account_number = esc_attr( rgget( $this->id . '.1', $value ) ); - $account_type = esc_attr( rgget( $this->id . '.2', $value ) ); - $routing_number = esc_attr( rgget( $this->id . '.3', $value ) ); - $account_holder_name= esc_attr( rgget( $this->id . '.4', $value ) ); - } - - - $tabindex = $this->get_tabindex(); - $account_type_field_input = GFFormsModel::get_input( $this, $this->id . '.2' ); - $account_type_options = $this->getAccountTypeSelectOptions( $account_type ); - - $account_types = $this->getAccountTypeList(); - //$radio_buttons = []; - //foreach ($account_types as $ac_key => $ac_label) - // $radio_buttons[]= ""; - - $account_type_label = rgar( $account_type_field_input, 'customLabel' ) != '' ? $account_type_field_input['customLabel'] : __( 'Account Type', 'gravity-forms-braintree' ); - $account_type_label = gf_apply_filters( array( 'gform_accounttype', $form_id ), $account_type_label, $form_id ); - if ( $is_sub_label_above ) { - $account_type_field = " + private $selected_payment_method = ''; + + /** + * @var string $type The field type. + */ + public $type = 'braintree_ach'; + + /** + * Return the field title, for use in the form editor. + * + * @return string + */ + public function get_form_editor_field_title() { + return __('ACH Form', 'gravity-forms-braintree'); + } + + /** + * Assign the field button to the Pricing Fields group. + * + * @return array + */ + public function get_form_editor_button() { + return ['group' => 'pricing_fields', 'text' => 'ACH Form']; + } + + /** + * The settings which should be available on the field in the form editor. + * + * @return array + */ + function get_form_editor_field_settings() { + return ['label_setting', 'label_placement_setting', 'admin_label_setting', 'description_setting', 'sub_labels_setting', + 'sub_label_placement_setting', 'error_message_setting', 'css_class_setting', 'conditional_logic_field_setting', + 'force_ssl_field_setting', 'rules_setting', 'input_placeholders_setting', + ]; + } + + /** + * Enable this field for use with conditional logic. + * + * @return bool + */ + public function is_conditional_logic_supported() { + return true; + } + + /** + * The scripts to be included in the form editor. + * + * @return string + */ + public function get_form_editor_inline_script_on_page_render() { + + } + + /** + * Override default button for the ACH Payments + * @param $button + * @param $form + * + * @return string + */ + function overrideSubmitButton($button, $form) { + $dom = new DOMDocument(); + $dom->loadHTML('' . $button); + $input = $dom->getElementsByTagName('input')->item(0); + //$input->removeAttribute('onkeypress'); + //$input->removeAttribute('onclick'); + $classes = $input->getAttribute('class'); + $classes .= " custom_ach_form_submit_btn"; + $input->setAttribute('class', $classes); + return $dom->saveHtml($input); + } + + /** + * Returns the fields input for backend and frontend + * @param array $form + * @param string $value + * @param null $entry + * + * @return string + */ + public function get_field_input($form, $value = '', $entry = null) { + add_filter('gform_submit_button', [$this, 'overrideSubmitButton'], 10, 2); + $is_entry_detail = $this->is_entry_detail(); + $is_form_editor = $this->is_form_editor(); + + $form_id = $form['id']; + $id = intval($this->id); + $field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; + $form_id = ( $is_entry_detail || $is_form_editor ) && empty($form_id) ? rgget('id') : $form_id; + + $disabled_text = $is_form_editor ? "disabled='disabled'" : ''; + $class_suffix = $is_entry_detail ? '_admin' : ''; + + $sub_label_placement = rgar($form, 'subLabelPlacement'); + $field_sub_label_placement = $this->subLabelPlacement; + $is_sub_label_above = $field_sub_label_placement == 'above' || ( empty($field_sub_label_placement) && $sub_label_placement == 'above' ); + $sub_label_class_attribute = $field_sub_label_placement == 'hidden_label' ? "class='hidden_sub_label screen-reader-text'" : ''; + + $account_number = ''; + $routing_number = ''; + $account_type = ''; + $account_holder_name = ''; + $autocomplete = RGFormsModel::is_html5_enabled() ? "autocomplete='off'" : ''; + + if (is_array($value)) { + $account_number = esc_attr(rgget($this->id . '.1', $value)); + $account_type = esc_attr(rgget($this->id . '.2', $value)); + $routing_number = esc_attr(rgget($this->id . '.3', $value)); + $account_holder_name = esc_attr(rgget($this->id . '.4', $value)); + } + + + $tabindex = $this->get_tabindex(); + $account_type_field_input = GFFormsModel::get_input($this, $this->id . '.2'); + $account_type_options = $this->getAccountTypeSelectOptions($account_type); + + $account_types = $this->getAccountTypeList(); + //$radio_buttons = []; + //foreach ($account_types as $ac_key => $ac_label) + // $radio_buttons[]= ""; + + $account_type_label = rgar($account_type_field_input, 'customLabel') != '' ? $account_type_field_input['customLabel'] : __('Account Type', 'gravity-forms-braintree'); + $account_type_label = gf_apply_filters(array('gform_accounttype', $form_id), $account_type_label, $form_id); + if ($is_sub_label_above) { + $account_type_field = " "; - } else { - $account_type_field = " + } else { + $account_type_field = " "; - } + } - $tabindex = $this->get_tabindex(); - $routing_number_field_input = GFFormsModel::get_input( $this, $this->id . '.3' ); - $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; - $routing_number_label = rgar( $routing_number_field_input, 'customLabel' ) != '' ? $routing_number_field_input['customLabel'] : __( 'Routing Number', 'gravity-forms-braintree' ); - $routing_number_label = gf_apply_filters( array( 'gform_routingnumber', $form_id ), $routing_number_label, $form_id ); + $tabindex = $this->get_tabindex(); + $routing_number_field_input = GFFormsModel::get_input($this, $this->id . '.3'); + $html5_output = !is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __('Only digits are allowed', 'gravity-forms-braintree') . "'" : ''; + $routing_number_label = rgar($routing_number_field_input, 'customLabel') != '' ? $routing_number_field_input['customLabel'] : __('Routing Number', 'gravity-forms-braintree'); + $routing_number_label = gf_apply_filters(array('gform_routingnumber', $form_id), $routing_number_label, $form_id); - $routing_number_placeholder = $this->get_input_placeholder_attribute( $routing_number_field_input ); - if ( $is_sub_label_above ) { - $routing_field = " + $routing_number_placeholder = $this->get_input_placeholder_attribute($routing_number_field_input); + if ($is_sub_label_above) { + $routing_field = " "; - } else { - $routing_field = " + } else { + $routing_field = " "; - } + } - $tabindex = $this->get_tabindex(); - $account_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' ); - $html5_output = ! is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __( 'Only digits are allowed', 'gravity-forms-braintree' ) . "'" : ''; - $account_number_label = rgar( $account_number_field_input, 'customLabel' ) != '' ? $account_number_field_input['customLabel'] : __( 'Account Number', 'gravity-forms-braintree' ); - $account_number_label = gf_apply_filters( array( 'gform_1', $form_id ), $account_number_label, $form_id ); + $tabindex = $this->get_tabindex(); + $account_number_field_input = GFFormsModel::get_input($this, $this->id . '.1'); + $html5_output = !is_admin() && GFFormsModel::is_html5_enabled() ? "pattern='[0-9]*' title='" . __('Only digits are allowed', 'gravity-forms-braintree') . "'" : ''; + $account_number_label = rgar($account_number_field_input, 'customLabel') != '' ? $account_number_field_input['customLabel'] : __('Account Number', 'gravity-forms-braintree'); + $account_number_label = gf_apply_filters(array('gform_1', $form_id), $account_number_label, $form_id); - $account_number_placeholder = $this->get_input_placeholder_attribute( $account_number_field_input ); - if ( $is_sub_label_above ) { - $account_field = " + $account_number_placeholder = $this->get_input_placeholder_attribute($account_number_field_input); + if ($is_sub_label_above) { + $account_field = " "; - } else { - $account_field = " + } else { + $account_field = " "; - } + } - $account_number_verification_field = ''; - if ( $is_sub_label_above ) { - $account_number_verification_field = " + $account_number_verification_field = ''; + if ($is_sub_label_above) { + $account_number_verification_field = " "; - } else { - $account_number_verification_field = " + } else { + $account_number_verification_field = " "; - } + } - $tabindex = $this->get_tabindex(); - $account_holder_name_field_input = GFFormsModel::get_input( $this, $this->id . '.4' ); - $account_holder_name_label = rgar( $account_holder_name_field_input, 'customLabel' ) != '' ? $account_holder_name_field_input['customLabel'] : __( 'Account Holder Name', 'gravity-forms-braintree' ); - $account_holder_name_label = gf_apply_filters( array( 'gform_accountholdername', $form_id ), $account_holder_name_label, $form_id ); + $tabindex = $this->get_tabindex(); + $account_holder_name_field_input = GFFormsModel::get_input($this, $this->id . '.4'); + $account_holder_name_label = rgar($account_holder_name_field_input, 'customLabel') != '' ? $account_holder_name_field_input['customLabel'] : __('Account Holder Name', 'gravity-forms-braintree'); + $account_holder_name_label = gf_apply_filters(array('gform_accountholdername', $form_id), $account_holder_name_label, $form_id); - $account_holder_name_placeholder = $this->get_input_placeholder_attribute( $account_holder_name_field_input ); - if ( $is_sub_label_above ) { - $account_holder_name_field = " + $account_holder_name_placeholder = $this->get_input_placeholder_attribute($account_holder_name_field_input); + if ($is_sub_label_above) { + $account_holder_name_field = " "; - } else { - $account_holder_name_field = " + } else { + $account_holder_name_field = " "; - } - - return "
" . $account_type_field. $account_holder_name_field . $routing_field . $account_field . $account_number_verification_field . '
'; - - } - - /** - * Returns Braintree ACH Supported account types - * @return mixed|void - */ - public function getAccountTypeList() { - $account_types = apply_filters( 'angelleye_gravity_braintree_account_types', [ - 'S' => __( 'Savings', 'gravity-forms-braintree' ), - 'C' => __( 'Checking', 'gravity-forms-braintree' ), - ]); - return $account_types; - } - - /** - * Returns the account type options for select field - * @param $selected_value - * @param string $placeholder - * - * @return string - */ - private function getAccountTypeSelectOptions( $selected_value, $placeholder = '' ) { - if ( empty( $placeholder ) ) { - $placeholder = __( 'Select', 'gravity-forms-braintree' ); - } - $options = $this->getAccountTypeList(); - $str = ""; - foreach ( $options as $value => $label ) { - $selected = $selected_value == $value ? "selected='selected'" : ''; - $str .= ""; - } - - return $str; - } - - public function get_field_label_class(){ - return 'gfield_label gfield_label_before_complex'; - } - - public function is_value_submission_empty( $form_id ) { - return false; - } - - /** - * When customer chooses ACH form method then avoid credit card field validation errors - * @param $validation_result - * - * @return mixed - */ - function customCCValidation($validation_result){ - $form = $validation_result['form']; - $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - - if($this->selected_payment_method !== 'braintree_ach') - return $validation_result; - - $failed_validation = 0; - if(isset($form['fields'])) { - - foreach ($form['fields'] as $key => $single_field) { - if ($single_field->type == 'creditcard') { - $form['fields'][$key]['failed_validation'] = false; - $form['fields'][$key]['validation_message'] = ''; - }else if($single_field['failed_validation']) - $failed_validation++; - } - } - - $validation_result['form']=$form; - if($failed_validation == 0){ - $validation_result['failed_validation_page'] = "1"; - $validation_result['is_valid'] = true; - } - - return $validation_result; - } - - /** - * Constructor to add custom validation filter to exclude CC validation when ACH payment method is selected - * Angelleye_Gravity_Braintree_ACH_Field constructor. - * - * @param array $data - */ - public function __construct( $data = array() ) { - parent::__construct($data); - add_filter( 'gform_validation', [$this, 'customCCValidation'], 50 ); - } - - /** - * Validate the user input - * @param array|string $value - * @param array $form - */ - public function validate( $value, $form ) { - - //check if toggle field exist - $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); - - if($this->selected_payment_method!=='braintree_ach') { - return; - } - - $account_number = rgpost( 'input_' . $this->id . '_1' ); - $routing_number = rgpost( 'input_' . $this->id . '_2' ); - $account_type = rgpost( 'input_' . $this->id . '_3' ); - $account_holder_name= rgpost( 'input_' . $this->id . '_4' ); - - //$this->isRequired && - if ( ( empty( $account_number ) || empty( $routing_number ) || empty( $account_type ) || empty($account_holder_name) ) ) { - $this->failed_validation = true; - $this->validation_message = empty( $this->errorMessage ) ? __( 'Please enter your bank account information.', 'gravity-forms-braintree' ) : $this->errorMessage; - } elseif ( !empty( $account_number ) ) { - - if ( empty( $routing_number ) ) { - $this->failed_validation = true; - $this->validation_message = __( "Please enter your bank account's routing number.", 'gravity-forms-braintree' ); - } - if ( empty( $account_type ) ) { - $this->failed_validation = true; - $this->validation_message = __( "Please select the account type.", 'gravity-forms-braintree' ); - } - - if ( empty( $account_holder_name ) ) { - $this->failed_validation = true; - $this->validation_message = __( "Please enter account holder name.", 'gravity-forms-braintree' ); - } - } - } - - /** - * Shows the filled information by the users on frontend form - * @param array $field_values - * @param bool $get_from_post_global_var - * - * @return array|string - */ - public function get_value_submission( $field_values, $get_from_post_global_var = true ) { - - if ( $get_from_post_global_var ) { - $value[ $this->id . '.1' ] = $this->get_input_value_submission( 'input_' . $this->id . '_1', rgar( @$this->inputs[0], 'name' ), $field_values, true ); - $value[ $this->id . '.2' ] = $this->get_input_value_submission( 'input_' . $this->id . '_2', rgar( @$this->inputs[1], 'name' ), $field_values, true ); - $value[ $this->id . '.3' ] = $this->get_input_value_submission( 'input_' . $this->id . '_3', rgar( @$this->inputs[2], 'name' ), $field_values, true ); - $value[ $this->id . '.4' ] = $this->get_input_value_submission( 'input_' . $this->id . '_4', rgar( @$this->inputs[3], 'name' ), $field_values, true ); - } else { - $value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var ); - } - return $value; - } - - /** - * Returns the ACH form entry input values - * @return array|null - */ - public function get_entry_inputs() { - $inputs = array(); - if(is_array($this->inputs)) { - foreach ( $this->inputs as $input ) { - if ( in_array( $input['id'], array( - $this->id . '.1', - $this->id . '.2', - $this->id . '.3', - $this->id . '.4' - ) ) ) { - $inputs[] = $input; - } - } - } - - return $inputs; - } - - /** - * Format the entry value for display on the entries list page. - * - * Return a value that's safe to display on the page. - * - * @param string|array $value The field value. - * @param array $entry The Entry Object currently being processed. - * @param string $field_id The field or input ID currently being processed. - * @param array $columns The properties for the columns being displayed on the entry list page. - * @param array $form The Form Object currently being processed. - * - * @return string - */ - public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) { - - $allowable_tags = $this->get_allowable_tags( $form['id'] ); - - list( $input_id, $field_id ) = rgexplode( '.', $field_id, 2 ); - switch($field_id){ - case 2: - $return = $value=='C'?'Checking':'Savings'; - break; - case 1: - case 3: - case 4: - default: - if ( $allowable_tags === false ) { - // The value is unsafe so encode the value. - $return = esc_html( $value ); - } else { - // The value contains HTML but the value was sanitized before saving. - $return = $value; - } - } - - return $return; - } - - /** - * Returns the ACH form value on Entry detail page - * @param array|string $value - * @param string $currency - * @param bool $use_text - * @param string $format - * @param string $media - * - * @return string - */ - public function get_value_entry_detail( $value, $currency = '', $use_text = false, $format = 'html', $media = 'screen' ) { - - if ( is_array( $value ) ) { - $account_number = trim( rgget( $this->id . '.1', $value ) ); - $account_type = trim( rgget( $this->id . '.2', $value ) ); - $routing_number = trim( rgget( $this->id . '.3', $value ) ); - $account_holder_name = trim( rgget( $this->id . '.4', $value ) ); - if($account_number=='') - return 'N/A'; - if($format=='html') - return "Account Number: $account_number
-Account Type: ".($account_type=='s'?'Savings':'Checking')."
+ } + + return "
" . $account_type_field . $account_holder_name_field . $routing_field . $account_field . $account_number_verification_field . '
'; + } + + /** + * Returns Braintree ACH Supported account types + * @return mixed|void + */ + public function getAccountTypeList() { + $account_types = apply_filters('angelleye_gravity_braintree_account_types', [ + 'S' => __('Savings', 'gravity-forms-braintree'), + 'C' => __('Checking', 'gravity-forms-braintree'), + ]); + return $account_types; + } + + /** + * Returns the account type options for select field + * @param $selected_value + * @param string $placeholder + * + * @return string + */ + private function getAccountTypeSelectOptions($selected_value, $placeholder = '') { + if (empty($placeholder)) { + $placeholder = __('Select', 'gravity-forms-braintree'); + } + $options = $this->getAccountTypeList(); + $str = ""; + foreach ($options as $value => $label) { + $selected = $selected_value == $value ? "selected='selected'" : ''; + $str .= ""; + } + + return $str; + } + + public function get_field_label_class() { + return 'gfield_label gfield_label_before_complex'; + } + + public function is_value_submission_empty($form_id) { + return false; + } + + /** + * When customer chooses ACH form method then avoid credit card field validation errors + * @param $validation_result + * + * @return mixed + */ + function customCCValidation($validation_result) { + $form = $validation_result['form']; + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); + + if ($this->selected_payment_method !== 'braintree_ach') + return $validation_result; + + $failed_validation = 0; + if (isset($form['fields'])) { + + foreach ($form['fields'] as $key => $single_field) { + if ($single_field->type == 'creditcard') { + $form['fields'][$key]['failed_validation'] = false; + $form['fields'][$key]['validation_message'] = ''; + } else if ($single_field['failed_validation']) + $failed_validation++; + } + } + + $validation_result['form'] = $form; + if ($failed_validation == 0) { + $validation_result['failed_validation_page'] = "1"; + $validation_result['is_valid'] = true; + } + + return $validation_result; + } + + /** + * Constructor to add custom validation filter to exclude CC validation when ACH payment method is selected + * Angelleye_Gravity_Braintree_ACH_Field constructor. + * + * @param array $data + */ + public function __construct($data = array()) { + parent::__construct($data); + add_filter('gform_validation', [$this, 'customCCValidation'], 50); + } + + /** + * Validate the user input + * @param array|string $value + * @param array $form + */ + public function validate($value, $form) { + + //check if toggle field exist + $this->selected_payment_method = getAngelleyeBraintreePaymentMethod($form); + + if ($this->selected_payment_method !== 'braintree_ach') { + return; + } + + $account_number = rgpost('input_' . $this->id . '_1'); + $routing_number = rgpost('input_' . $this->id . '_2'); + $account_type = rgpost('input_' . $this->id . '_3'); + $account_holder_name = rgpost('input_' . $this->id . '_4'); + + //$this->isRequired && + if (( empty($account_number) || empty($routing_number) || empty($account_type) || empty($account_holder_name))) { + $this->failed_validation = true; + $this->validation_message = empty($this->errorMessage) ? __('Please enter your bank account information.', 'gravity-forms-braintree') : $this->errorMessage; + } elseif (!empty($account_number)) { + + if (empty($routing_number)) { + $this->failed_validation = true; + $this->validation_message = __("Please enter your bank account's routing number.", 'gravity-forms-braintree'); + } + if (empty($account_type)) { + $this->failed_validation = true; + $this->validation_message = __("Please select the account type.", 'gravity-forms-braintree'); + } + + if (empty($account_holder_name)) { + $this->failed_validation = true; + $this->validation_message = __("Please enter account holder name.", 'gravity-forms-braintree'); + } + } + } + + /** + * Shows the filled information by the users on frontend form + * @param array $field_values + * @param bool $get_from_post_global_var + * + * @return array|string + */ + public function get_value_submission($field_values, $get_from_post_global_var = true) { + + if ($get_from_post_global_var) { + $value[$this->id . '.1'] = $this->get_input_value_submission('input_' . $this->id . '_1', rgar(@$this->inputs[0], 'name'), $field_values, true); + $value[$this->id . '.2'] = $this->get_input_value_submission('input_' . $this->id . '_2', rgar(@$this->inputs[1], 'name'), $field_values, true); + $value[$this->id . '.3'] = $this->get_input_value_submission('input_' . $this->id . '_3', rgar(@$this->inputs[2], 'name'), $field_values, true); + $value[$this->id . '.4'] = $this->get_input_value_submission('input_' . $this->id . '_4', rgar(@$this->inputs[3], 'name'), $field_values, true); + } else { + $value = $this->get_input_value_submission('input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var); + } + return $value; + } + + /** + * Returns the ACH form entry input values + * @return array|null + */ + public function get_entry_inputs() { + $inputs = array(); + if (is_array($this->inputs)) { + foreach ($this->inputs as $input) { + if (in_array($input['id'], array( + $this->id . '.1', + $this->id . '.2', + $this->id . '.3', + $this->id . '.4' + ))) { + $inputs[] = $input; + } + } + } + + return $inputs; + } + + /** + * Format the entry value for display on the entries list page. + * + * Return a value that's safe to display on the page. + * + * @param string|array $value The field value. + * @param array $entry The Entry Object currently being processed. + * @param string $field_id The field or input ID currently being processed. + * @param array $columns The properties for the columns being displayed on the entry list page. + * @param array $form The Form Object currently being processed. + * + * @return string + */ + public function get_value_entry_list($value, $entry, $field_id, $columns, $form) { + + $allowable_tags = $this->get_allowable_tags($form['id']); + + list( $input_id, $field_id ) = rgexplode('.', $field_id, 2); + switch ($field_id) { + case 2: + $return = $value == 'C' ? 'Checking' : 'Savings'; + break; + case 1: + case 3: + case 4: + default: + if ($allowable_tags === false) { + // The value is unsafe so encode the value. + $return = esc_html($value); + } else { + // The value contains HTML but the value was sanitized before saving. + $return = $value; + } + } + + return $return; + } + + /** + * Returns the ACH form value on Entry detail page + * @param array|string $value + * @param string $currency + * @param bool $use_text + * @param string $format + * @param string $media + * + * @return string + */ + public function get_value_entry_detail($value, $currency = '', $use_text = false, $format = 'html', $media = 'screen') { + + if (is_array($value)) { + $account_number = trim(rgget($this->id . '.1', $value)); + $account_type = trim(rgget($this->id . '.2', $value)); + $routing_number = trim(rgget($this->id . '.3', $value)); + $account_holder_name = trim(rgget($this->id . '.4', $value)); + if ($account_number == '') + return 'N/A'; + if ($format == 'html') + return "Account Number: $account_number
+Account Type: " . ($account_type == 's' ? 'Savings' : 'Checking') . "
Routing Number: $routing_number
Account Holder: $account_holder_name
"; - } else { - return ''; - } - } - - /** - * Mask the values before saving - * @param string $value - * @param array $form - * @param string $input_name - * @param int $lead_id - * @param array $lead - * - * @return array|string - */ - public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) { - list( $input_token, $field_id_token, $input_id ) = rgexplode( '_', $input_name, 3 ); - if ( $input_id == '1' || $input_id == '3' ) { - $value = str_replace( ' ', '', $value ); - $card_number_length = strlen( $value ); - $value = substr( $value, - 4, 4 ); - $value = str_pad( $value, $card_number_length, 'X', STR_PAD_LEFT ); - } - - return $this->sanitize_entry_value( $value, $form['id'] ); - } + } else { + return ''; + } + } + + /** + * Mask the values before saving + * @param string $value + * @param array $form + * @param string $input_name + * @param int $lead_id + * @param array $lead + * + * @return array|string + */ + public function get_value_save_entry($value, $form, $input_name, $lead_id, $lead) { + list( $input_token, $field_id_token, $input_id ) = rgexplode('_', $input_name, 3); + if ($input_id == '1' || $input_id == '3') { + $value = str_replace(' ', '', $value); + $card_number_length = strlen($value); + $value = substr($value, - 4, 4); + $value = str_pad($value, $card_number_length, 'X', STR_PAD_LEFT); + } + + return $this->sanitize_entry_value($value, $form['id']); + } } From c0c26ff8874a17551cff5f08b69c612304f58232 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Wed, 26 Jan 2022 16:12:56 +0530 Subject: [PATCH 95/99] Updates changelog and version for v4.0.5 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index b1231f2..70e21c5 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0.4 + * Version: 4.0.5 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0.4'; + public static $version = '4.0.5'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 49411a7..ca3a0f3 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0.4'; + protected $_version = '4.0.5'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; protected $_path = 'gravity-forms-braintree/lib/class.plugify-gform-braintree.php'; diff --git a/readme.txt b/readme.txt index 754b4d8..867f098 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 -Tested up to: 5.8.3 -Stable tag: 4.0.4 +Tested up to: 5.9 +Stable tag: 4.0.5 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.5 - 01.26.2022 = +* Feature - Added Gravity Forms version 2.5.16 capability. ([GFB-42](https://github.com/angelleye/gravity-forms-braintree/pull/39)) + = 4.0.4 - 01.17.2022 = * Fix - Resolved PHP Fatal error. ([GFB-41](https://github.com/angelleye/gravity-forms-braintree/pull/38)) From aa8ca421ae3b5e1c121751e625f1a5684dd835d0 Mon Sep 17 00:00:00 2001 From: Jaydeep Rajgor Date: Mon, 17 Apr 2023 11:56:46 +0530 Subject: [PATCH 96/99] Adjustments to resolve theme conflict, GFB-40 --- includes/class-angelleye-gravity-braintree-ach-field.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/class-angelleye-gravity-braintree-ach-field.php b/includes/class-angelleye-gravity-braintree-ach-field.php index 9ba9d5c..6cbc3f1 100644 --- a/includes/class-angelleye-gravity-braintree-ach-field.php +++ b/includes/class-angelleye-gravity-braintree-ach-field.php @@ -70,6 +70,10 @@ function overrideSubmitButton($button, $form) { $dom = new DOMDocument(); $dom->loadHTML('' . $button); $input = $dom->getElementsByTagName('input')->item(0); + if( empty( $input ) ){ + $input = $dom->getElementsByTagName('button')->item(0); + } + //$input->removeAttribute('onkeypress'); //$input->removeAttribute('onclick'); $classes = $input->getAttribute('class'); From 47cb479bb3b2ba43d10dee181600a49aee6b3f54 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Tue, 18 Apr 2023 14:28:17 +0530 Subject: [PATCH 97/99] Updates changelog and version for v4.0.6 --- angelleye-gravity-forms-braintree.php | 4 ++-- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 70e21c5..544b6e3 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 4.0.5 + * Version: 4.0.6 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree @@ -39,7 +39,7 @@ class AngelleyeGravityFormsBraintree{ protected static $instance = null; public static $plugin_base_file; - public static $version = '4.0.5'; + public static $version = '4.0.6'; public static function getInstance() { diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index ca3a0f3..5e8b0c1 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '4.0.5'; + protected $_version = '4.0.6'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; protected $_path = 'gravity-forms-braintree/lib/class.plugify-gform-braintree.php'; diff --git a/readme.txt b/readme.txt index 867f098..c31f825 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 Tested up to: 5.9 -Stable tag: 4.0.5 +Stable tag: 4.0.6 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 4.0.6 - 04.18.2023 = +* Fix - Adjustments to resolve theme conflict. ([GFB-40](https://github.com/angelleye/gravity-forms-braintree/pull/44)) + = 4.0.5 - 01.26.2022 = * Feature - Added Gravity Forms version 2.5.16 capability. ([GFB-42](https://github.com/angelleye/gravity-forms-braintree/pull/39)) From f39bf28c25950aec4489f0f612b169752be22b47 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Tue, 18 Apr 2023 14:30:49 +0530 Subject: [PATCH 98/99] Updates changelog and version for v4.0.6 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index c31f825..c1367b5 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 5.0 -Tested up to: 5.9 +Tested up to: 6.2 Stable tag: 4.0.6 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html From 00b9b33d4296d31a6d78ebe7365bb8afe33b9e28 Mon Sep 17 00:00:00 2001 From: Ravindra112001 Date: Mon, 8 May 2023 15:37:06 +0530 Subject: [PATCH 99/99] Resolve beaintree payment error while using credit card field, GFB-46 --- ...angelleye-gravity-braintree-creditcard.php | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/includes/class-angelleye-gravity-braintree-creditcard.php b/includes/class-angelleye-gravity-braintree-creditcard.php index 53558b5..79b0dab 100644 --- a/includes/class-angelleye-gravity-braintree-creditcard.php +++ b/includes/class-angelleye-gravity-braintree-creditcard.php @@ -90,24 +90,49 @@ public function get_field_input( $form, $value = '', $entry = null ) {
'+$('.custom_fields_template').html()+' Remove
'+$('.custom_fields_template').html()+' Remove

Custom Fields Add Custom Field

Custom Fields Add Custom Field

+ \ No newline at end of file From 750d16625bdf4de0f68baf11cf2579b88bf386c5 Mon Sep 17 00:00:00 2001 From: angelleye Date: Tue, 22 Oct 2019 11:14:29 -0500 Subject: [PATCH 51/99] Updates changelog, GFB-15 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index b90f652..ef6d21a 100644 --- a/readme.txt +++ b/readme.txt @@ -65,7 +65,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == = 2.2.0 = 10.16.2019 = -* Feature - Adds Braintree field mapping capability. ([GFB-12](https://github.com/angelleye/gravity-forms-braintree/pull/14)) +* Feature - Adds Braintree field mapping capability. ([GFB-12](https://github.com/angelleye/gravity-forms-braintree/pull/14)) ([GFB-15](https://github.com/angelleye/gravity-forms-braintree/pull/16)) * Tweak - Adds a notice if you try to activate the Braintree Payments extension without Gravity Forms active. = 2.1.3 - 07.23.2019 = From db93593e3cee31dad38b31822bdade596a5dfe4a Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Wed, 20 Nov 2019 14:23:05 +0530 Subject: [PATCH 52/99] Updates version details for v2.2.1 --- angelleye-gravity-forms-braintree.php | 2 +- readme.txt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 7d9f9e7..7148205 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.2.0 + * Version: 2.2.1 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/readme.txt b/readme.txt index ef6d21a..fe8ce5b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.2.4 -Stable tag: 2.2.0 +Tested up to: 5.3 +Stable tag: 2.2.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.2.0 = 11.20.2019 = +* Verification - WordPress 5.3 compatibility. + = 2.2.0 = 10.16.2019 = * Feature - Adds Braintree field mapping capability. ([GFB-12](https://github.com/angelleye/gravity-forms-braintree/pull/14)) ([GFB-15](https://github.com/angelleye/gravity-forms-braintree/pull/16)) * Tweak - Adds a notice if you try to activate the Braintree Payments extension without Gravity Forms active. From 2886b6214389f8a2dd2e416f4481125fc534b458 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Thu, 28 Nov 2019 15:49:42 +0530 Subject: [PATCH 53/99] Updater Install Notification should be dismissable, GFB-16 --- assets/css/gravity-forms-braintree-admin.css | 4 ++++ assets/js/gravity-forms-braintree-admin.js | 17 +++++++++++++++++ includes/angelleye-functions.php | 12 +++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/assets/css/gravity-forms-braintree-admin.css b/assets/css/gravity-forms-braintree-admin.css index 3d1d90e..ffc87b4 100644 --- a/assets/css/gravity-forms-braintree-admin.css +++ b/assets/css/gravity-forms-braintree-admin.css @@ -71,4 +71,8 @@ color: #C5C5C5; -webkit-font-smoothing: antialiased; } +.updater-dismissible { + padding-right: 38px; + position: relative; +} diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index c13f21b..45c6ea9 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -18,6 +18,23 @@ jQuery(function () { }; jQuery.post(ajaxurl, param); } + jQuery(document).on('click', '#angelleye-updater-notice .notice-dismiss', function( event ) { + var r = confirm("If you do not install the Updater plugin you will not receive automated updates for Angell EYE products going forward!"); + if (r == true) { + data = { + action : 'angelleye_updater_dismissible_admin_notice' + }; + jQuery.post(ajaxurl, data, function (response) { + var $el = jQuery( '#angelleye-updater-notice' ); + event.preventDefault(); + $el.fadeTo( 100, 0, function() { + $el.slideUp( 100, function() { + $el.remove(); + }); + }); + }); + } + }); }); jQuery(document).ready(function ($) { diff --git a/includes/angelleye-functions.php b/includes/angelleye-functions.php index aa876bc..1d33b50 100644 --- a/includes/angelleye-functions.php +++ b/includes/angelleye-functions.php @@ -78,8 +78,14 @@ function angell_updater_notice() { $message = ' Activate the Angell EYE Updater plugin to get updates for your Angell EYE plugins.'; } } - echo '

' . $message . '

' . "\n"; + echo '

' . $message . '

' . "\n"; } - - add_action('admin_notices', 'angell_updater_notice'); + + function angelleye_updater_dismissible_admin_notice() { + set_transient( 'angelleye_updater_notice_hide', 'yes', MONTH_IN_SECONDS ); + } + if ( false === ( $angelleye_updater_notice_hide = get_transient( 'angelleye_updater_notice_hide' ) ) ) { + add_action('admin_notices', 'angell_updater_notice'); + } + add_action( 'wp_ajax_angelleye_updater_dismissible_admin_notice', 'angelleye_updater_dismissible_admin_notice' ); } \ No newline at end of file From 3d47d04d6d00b6c53118c5020bbc7cedf15cac9b Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 16 Dec 2019 14:48:27 +0530 Subject: [PATCH 54/99] Updater Install Notification should be dismissable, GFB-16 --- assets/js/gravity-forms-braintree-admin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index 45c6ea9..c591f48 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -18,10 +18,10 @@ jQuery(function () { }; jQuery.post(ajaxurl, param); } - jQuery(document).on('click', '#angelleye-updater-notice .notice-dismiss', function( event ) { + jQuery(document).off('click', '#angelleye-updater-notice .notice-dismiss').on('click', '#angelleye-updater-notice .notice-dismiss',function(event) { var r = confirm("If you do not install the Updater plugin you will not receive automated updates for Angell EYE products going forward!"); if (r == true) { - data = { + var data = { action : 'angelleye_updater_dismissible_admin_notice' }; jQuery.post(ajaxurl, data, function (response) { From 4fdc9301a62616f18a43e230030baaf00a7ad1f8 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 23 Dec 2019 15:06:04 +0530 Subject: [PATCH 55/99] Updates changelog, PIFW-33 --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index fe8ce5b..10436e5 100644 --- a/readme.txt +++ b/readme.txt @@ -64,6 +64,9 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == += 2.2.1 - 23.12.2019 = +* Tweak - Adjustment to Updater plugin notice dismissible. ([PIFW-33](https://github.com/angelleye/gravity-forms-braintree/pull/17)) + = 2.2.0 = 11.20.2019 = * Verification - WordPress 5.3 compatibility. From aaff9c11fcdbc4ef27eef3c90c3b02978e4db973 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 23 Dec 2019 15:11:03 +0530 Subject: [PATCH 56/99] Updates changelog, GFB-16 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 10436e5..9f150f1 100644 --- a/readme.txt +++ b/readme.txt @@ -65,7 +65,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == = 2.2.1 - 23.12.2019 = -* Tweak - Adjustment to Updater plugin notice dismissible. ([PIFW-33](https://github.com/angelleye/gravity-forms-braintree/pull/17)) +* Tweak - Adjustment to Updater plugin notice dismissible. ([GFB-16](https://github.com/angelleye/gravity-forms-braintree/pull/17)) = 2.2.0 = 11.20.2019 = * Verification - WordPress 5.3 compatibility. From 6b8ca00b1c862650d2fce749b46baaa486bd4312 Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Fri, 27 Dec 2019 17:54:54 +0530 Subject: [PATCH 57/99] Updates changelog, GFB-16 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 9f150f1..3b6b010 100644 --- a/readme.txt +++ b/readme.txt @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.2.1 - 23.12.2019 = += 2.2.1 - 12.XX.2019 = * Tweak - Adjustment to Updater plugin notice dismissible. ([GFB-16](https://github.com/angelleye/gravity-forms-braintree/pull/17)) = 2.2.0 = 11.20.2019 = From 6358c9c1585abaa7e92a680d8463c53c4a3a9abd Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 30 Dec 2019 14:02:57 +0530 Subject: [PATCH 58/99] Updates version details for v2.2.2 --- angelleye-gravity-forms-braintree.php | 2 +- lib/class.plugify-gform-braintree.php | 2 +- readme.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/angelleye-gravity-forms-braintree.php b/angelleye-gravity-forms-braintree.php index 7148205..8e19f9b 100644 --- a/angelleye-gravity-forms-braintree.php +++ b/angelleye-gravity-forms-braintree.php @@ -4,7 +4,7 @@ * Plugin URI: https://angelleye.com/products/gravity-forms-braintree-payments * Description: Allow your customers to purchase goods and services through Gravity Forms via Braintree Payments. * Author: Angell EYE - * Version: 2.2.1 + * Version: 2.2.2 * Author URI: https://angelleye.com * Text Domain: angelleye-gravity-forms-braintree diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 6a0ef15..5736021 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -4,7 +4,7 @@ final class Plugify_GForm_Braintree extends GFPaymentAddOn { - protected $_version = '1.0'; + protected $_version = '2.2.2'; protected $_min_gravityforms_version = '1.8.7.16'; protected $_slug = 'gravity-forms-braintree'; diff --git a/readme.txt b/readme.txt index 3b6b010..4880503 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: angelleye, Plugify, hello@lukerollans.me, gravityplus Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CQZZGGMF78VY&source=url Tags: gravity form, gravity forms, credit card, credit cards, payment, payments, braintree Requires at least: 3.8 -Tested up to: 5.3 -Stable tag: 2.2.1 +Tested up to: 5.3.2 +Stable tag: 2.2.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From 42683a4f96dca87cdb0a8e18f8037e461329737e Mon Sep 17 00:00:00 2001 From: kcppdevelopers Date: Mon, 30 Dec 2019 14:09:19 +0530 Subject: [PATCH 59/99] Updates version details for v2.2.2 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 4880503..b3bcc5f 100644 --- a/readme.txt +++ b/readme.txt @@ -64,7 +64,7 @@ In the search field type Gravity Forms Braintree Payments and click Search Plugi == Changelog == -= 2.2.1 - 12.XX.2019 = += 2.2.2 - 12.30.2019 = * Tweak - Adjustment to Updater plugin notice dismissible. ([GFB-16](https://github.com/angelleye/gravity-forms-braintree/pull/17)) = 2.2.0 = 11.20.2019 = From 93e80c373beffa3c38fd0259cac7e033e23224f4 Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 28 Apr 2020 11:09:54 +0530 Subject: [PATCH 60/99] Braintree library upgraded from 3 to 5.0, GFB-18 --- lib/Braintree.php | 4 +- lib/Braintree/AccountUpdaterDailyReport.php | 1 - lib/Braintree/AchMandate.php | 2 - lib/Braintree/AddOn.php | 15 +- lib/Braintree/AddOnGateway.php | 1 - lib/Braintree/Address.php | 6 +- lib/Braintree/AddressGateway.php | 3 - lib/Braintree/AmexExpressCheckoutCard.php | 18 +- lib/Braintree/AndroidPayCard.php | 9 +- lib/Braintree/ApplePayCard.php | 8 +- lib/Braintree/ApplePayGateway.php | 1 - lib/Braintree/ApplePayOptions.php | 1 - lib/Braintree/AuthorizationAdjustment.php | 3 +- lib/Braintree/Base.php | 6 +- lib/Braintree/BinData.php | 12 +- lib/Braintree/ClientToken.php | 1 - lib/Braintree/ClientTokenGateway.php | 1 - lib/Braintree/CoinbaseAccount.php | 110 ------- lib/Braintree/Collection.php | 3 - lib/Braintree/Configuration.php | 25 +- .../ConnectedMerchantPayPalStatusChanged.php | 1 - .../ConnectedMerchantStatusTransitioned.php | 1 - lib/Braintree/CredentialsParser.php | 1 - lib/Braintree/CreditCard.php | 31 +- lib/Braintree/CreditCardGateway.php | 70 +---- lib/Braintree/CreditCardVerification.php | 29 +- .../CreditCardVerificationGateway.php | 1 - .../CreditCardVerificationSearch.php | 1 - lib/Braintree/Customer.php | 101 ++---- lib/Braintree/CustomerGateway.php | 85 +----- lib/Braintree/CustomerSearch.php | 1 - lib/Braintree/Descriptor.php | 6 +- lib/Braintree/Digest.php | 5 +- lib/Braintree/Disbursement.php | 1 - lib/Braintree/DisbursementDetails.php | 7 +- lib/Braintree/Discount.php | 15 +- lib/Braintree/DiscountGateway.php | 1 - lib/Braintree/Dispute.php | 25 +- lib/Braintree/Dispute/EvidenceDetails.php | 10 +- .../Dispute/StatusHistoryDetails.php | 8 +- lib/Braintree/Dispute/TransactionDetails.php | 2 - lib/Braintree/DisputeGateway.php | 2 - lib/Braintree/DisputeSearch.php | 1 - lib/Braintree/DocumentUpload.php | 8 +- lib/Braintree/DocumentUploadGateway.php | 2 - lib/Braintree/EndsWithNode.php | 1 - lib/Braintree/EqualityNode.php | 1 - lib/Braintree/Error/Codes.php | 189 +++++++----- lib/Braintree/Error/ErrorCollection.php | 16 +- lib/Braintree/Error/Validation.php | 1 - .../Error/ValidationErrorCollection.php | 7 +- lib/Braintree/EuropeBankAccount.php | 67 ---- lib/Braintree/Exception.php | 1 - lib/Braintree/Exception/Authentication.php | 1 - lib/Braintree/Exception/Authorization.php | 1 - lib/Braintree/Exception/Configuration.php | 2 - lib/Braintree/Exception/Connection.php | 1 - .../Exception/DownForMaintenance.php | 16 - lib/Braintree/Exception/ForgedQueryString.php | 20 -- lib/Braintree/Exception/GatewayTimeout.php | 15 + lib/Braintree/Exception/InvalidChallenge.php | 1 - lib/Braintree/Exception/InvalidSignature.php | 1 - lib/Braintree/Exception/NotFound.php | 2 - lib/Braintree/Exception/RequestTimeout.php | 14 + lib/Braintree/Exception/SSLCaFileNotFound.php | 2 - lib/Braintree/Exception/SSLCertificate.php | 2 - lib/Braintree/Exception/ServerError.php | 2 - .../Exception/ServiceUnavailable.php | 14 + .../TestOperationPerformedInProduction.php | 1 - lib/Braintree/Exception/Timeout.php | 2 - lib/Braintree/Exception/TooManyRequests.php | 2 - lib/Braintree/Exception/Unexpected.php | 2 - lib/Braintree/Exception/UpgradeRequired.php | 2 - lib/Braintree/Exception/ValidationsFailed.php | 2 - lib/Braintree/FacilitatedDetails.php | 7 +- lib/Braintree/FacilitatorDetails.php | 7 +- lib/Braintree/Gateway.php | 26 +- .../GrantedPaymentInstrumentUpdate.php | 1 - lib/Braintree/GraphQL.php | 6 +- lib/Braintree/GraphQLClient.php | 19 ++ lib/Braintree/Http.php | 11 +- lib/Braintree/IbanBankAccount.php | 57 ---- lib/Braintree/IdealPayment.php | 92 ------ lib/Braintree/IdealPaymentGateway.php | 104 ------- lib/Braintree/Instance.php | 1 - lib/Braintree/IsNode.php | 1 - lib/Braintree/KeyValueNode.php | 1 - lib/Braintree/LocalPaymentCompleted.php | 16 +- lib/Braintree/MasterpassCard.php | 13 +- lib/Braintree/Merchant.php | 1 - lib/Braintree/MerchantAccount.php | 11 +- .../MerchantAccount/AddressDetails.php | 1 - .../MerchantAccount/BusinessDetails.php | 1 - .../MerchantAccount/FundingDetails.php | 1 - .../MerchantAccount/IndividualDetails.php | 1 - lib/Braintree/MerchantAccountGateway.php | 38 +-- lib/Braintree/MerchantGateway.php | 1 - lib/Braintree/Modification.php | 1 - lib/Braintree/MultipleValueNode.php | 1 - lib/Braintree/MultipleValueOrTextNode.php | 1 - lib/Braintree/OAuthAccessRevocation.php | 3 - lib/Braintree/OAuthCredentials.php | 1 - lib/Braintree/OAuthGateway.php | 11 - lib/Braintree/OAuthResult.php | 1 - lib/Braintree/PaginatedCollection.php | 1 - lib/Braintree/PaginatedResult.php | 1 - lib/Braintree/PartialMatchNode.php | 1 - lib/Braintree/PartnerMerchant.php | 1 - lib/Braintree/PayPalAccount.php | 10 +- lib/Braintree/PayPalAccountGateway.php | 1 - lib/Braintree/PaymentInstrumentType.php | 18 +- lib/Braintree/PaymentMethod.php | 1 - lib/Braintree/PaymentMethodGateway.php | 153 ++++------ lib/Braintree/PaymentMethodNonce.php | 19 +- lib/Braintree/PaymentMethodNonceGateway.php | 13 +- lib/Braintree/PaymentMethodParser.php | 53 ++++ lib/Braintree/Plan.php | 18 +- lib/Braintree/PlanGateway.php | 1 - lib/Braintree/ProcessorResponseTypes.php | 14 + lib/Braintree/RangeNode.php | 1 - lib/Braintree/ResourceCollection.php | 1 - .../Result/CreditCardVerification.php | 16 +- lib/Braintree/Result/Error.php | 1 - lib/Braintree/Result/Successful.php | 1 - .../Result/UsBankAccountVerification.php | 5 +- .../RevokedPaymentMethodMetadata.php | 52 ++++ lib/Braintree/RiskData.php | 6 +- lib/Braintree/SamsungPayCard.php | 15 +- lib/Braintree/SettlementBatchSummary.php | 4 +- .../SettlementBatchSummaryGateway.php | 1 - lib/Braintree/SignatureService.php | 1 - lib/Braintree/Subscription.php | 34 ++- lib/Braintree/Subscription/StatusDetails.php | 3 +- lib/Braintree/SubscriptionGateway.php | 3 - lib/Braintree/SubscriptionSearch.php | 1 - lib/Braintree/Test/AuthenticationIds.php | 37 +++ lib/Braintree/Test/CreditCardNumbers.php | 4 +- lib/Braintree/Test/MerchantAccount.php | 1 - lib/Braintree/Test/Nonces.php | 19 +- lib/Braintree/Test/Transaction.php | 1 - lib/Braintree/Test/TransactionAmounts.php | 6 +- lib/Braintree/Test/VenmoSdk.php | 1 - lib/Braintree/TestingGateway.php | 1 - lib/Braintree/TextNode.php | 1 - lib/Braintree/ThreeDSecureInfo.php | 12 +- lib/Braintree/Transaction.php | 131 +++++--- lib/Braintree/Transaction/AddressDetails.php | 1 - .../AmexExpressCheckoutCardDetails.php | 1 - .../Transaction/AndroidPayCardDetails.php | 11 +- .../Transaction/ApplePayCardDetails.php | 15 +- lib/Braintree/Transaction/CoinbaseDetails.php | 38 --- .../Transaction/CreditCardDetails.php | 1 - lib/Braintree/Transaction/CustomerDetails.php | 1 - .../Transaction/EuropeBankAccountDetails.php | 24 -- .../Transaction/IdealPaymentDetails.php | 23 -- lib/Braintree/Transaction/LineItem.php | 4 - .../Transaction/LocalPaymentDetails.php | 44 +++ .../Transaction/MasterpassCardDetails.php | 2 +- lib/Braintree/Transaction/PayPalDetails.php | 19 +- .../Transaction/PayPalHereDetails.php | 43 +++ .../Transaction/SamsungPayCardDetails.php | 3 +- lib/Braintree/Transaction/StatusDetails.php | 1 - .../Transaction/SubscriptionDetails.php | 5 +- .../Transaction/UsBankAccountDetails.php | 1 - .../Transaction/VenmoAccountDetails.php | 1 - .../Transaction/VisaCheckoutCardDetails.php | 1 - lib/Braintree/TransactionGateway.php | 121 ++++---- lib/Braintree/TransactionLineItem.php | 20 +- lib/Braintree/TransactionLineItemGateway.php | 1 - lib/Braintree/TransactionSearch.php | 2 - lib/Braintree/TransparentRedirect.php | 100 ------ lib/Braintree/TransparentRedirectGateway.php | 289 ------------------ lib/Braintree/UnknownPaymentMethod.php | 1 - lib/Braintree/UsBankAccount.php | 3 +- lib/Braintree/UsBankAccountGateway.php | 1 - lib/Braintree/UsBankAccountVerification.php | 1 - .../UsBankAccountVerificationGateway.php | 2 - .../UsBankAccountVerificationSearch.php | 1 - lib/Braintree/Util.php | 40 ++- lib/Braintree/VenmoAccount.php | 10 +- lib/Braintree/Version.php | 5 +- lib/Braintree/VisaCheckoutCard.php | 13 +- lib/Braintree/WebhookNotification.php | 19 +- lib/Braintree/WebhookNotificationGateway.php | 2 - lib/Braintree/WebhookTesting.php | 1 - lib/Braintree/WebhookTestingGateway.php | 155 +++++++--- lib/Braintree/Xml.php | 2 - lib/Braintree/Xml/Generator.php | 5 - lib/Braintree/Xml/Parser.php | 1 - lib/class.plugify-gform-braintree.php | 18 +- 190 files changed, 1265 insertions(+), 1920 deletions(-) delete mode 100644 lib/Braintree/CoinbaseAccount.php delete mode 100644 lib/Braintree/EuropeBankAccount.php delete mode 100644 lib/Braintree/Exception/DownForMaintenance.php delete mode 100644 lib/Braintree/Exception/ForgedQueryString.php create mode 100644 lib/Braintree/Exception/GatewayTimeout.php create mode 100644 lib/Braintree/Exception/RequestTimeout.php create mode 100644 lib/Braintree/Exception/ServiceUnavailable.php create mode 100644 lib/Braintree/GraphQLClient.php delete mode 100644 lib/Braintree/IbanBankAccount.php delete mode 100644 lib/Braintree/IdealPayment.php delete mode 100644 lib/Braintree/IdealPaymentGateway.php create mode 100644 lib/Braintree/PaymentMethodParser.php create mode 100644 lib/Braintree/ProcessorResponseTypes.php create mode 100644 lib/Braintree/RevokedPaymentMethodMetadata.php create mode 100644 lib/Braintree/Test/AuthenticationIds.php delete mode 100644 lib/Braintree/Transaction/CoinbaseDetails.php delete mode 100644 lib/Braintree/Transaction/EuropeBankAccountDetails.php delete mode 100644 lib/Braintree/Transaction/IdealPaymentDetails.php delete mode 100644 lib/Braintree/Transaction/LineItem.php create mode 100644 lib/Braintree/Transaction/LocalPaymentDetails.php create mode 100644 lib/Braintree/Transaction/PayPalHereDetails.php delete mode 100644 lib/Braintree/TransparentRedirect.php delete mode 100644 lib/Braintree/TransparentRedirectGateway.php diff --git a/lib/Braintree.php b/lib/Braintree.php index 066107a..6a984c7 100644 --- a/lib/Braintree.php +++ b/lib/Braintree.php @@ -6,8 +6,8 @@ require_once(__DIR__ . DIRECTORY_SEPARATOR . 'autoload.php'); -if (version_compare(PHP_VERSION, '5.4.0', '<')) { - throw new Braintree_Exception('PHP version >= 5.4.0 required'); +if (version_compare(PHP_VERSION, '7.2.0', '<')) { + throw new Braintree_Exception('PHP version >= 7.2.0 required'); } class Braintree { diff --git a/lib/Braintree/AccountUpdaterDailyReport.php b/lib/Braintree/AccountUpdaterDailyReport.php index 226bdfe..d6a32a8 100644 --- a/lib/Braintree/AccountUpdaterDailyReport.php +++ b/lib/Braintree/AccountUpdaterDailyReport.php @@ -40,4 +40,3 @@ public function __toString() Util::attributesToString($displayAttributes) .']'; } } -class_alias('Braintree\AccountUpdaterDailyReport', 'Braintree_AccountUpdaterDailyReport'); diff --git a/lib/Braintree/AchMandate.php b/lib/Braintree/AchMandate.php index 86eeea6..569ba56 100644 --- a/lib/Braintree/AchMandate.php +++ b/lib/Braintree/AchMandate.php @@ -3,7 +3,6 @@ /** * Braintree AchMandate module - * PHP Version 5 * * @package Braintree * @@ -52,4 +51,3 @@ public static function factory($attributes) } } -class_alias('Braintree\AchMandate', 'Braintree_Mandate'); diff --git a/lib/Braintree/AddOn.php b/lib/Braintree/AddOn.php index 04c1705..e98b44b 100644 --- a/lib/Braintree/AddOn.php +++ b/lib/Braintree/AddOn.php @@ -1,6 +1,20 @@ addOn()->all(); } } -class_alias('Braintree\AddOn', 'Braintree_AddOn'); diff --git a/lib/Braintree/AddOnGateway.php b/lib/Braintree/AddOnGateway.php index 9ecf942..bc795b0 100644 --- a/lib/Braintree/AddOnGateway.php +++ b/lib/Braintree/AddOnGateway.php @@ -50,4 +50,3 @@ public function all() ); } } -class_alias('Braintree\AddOnGateway', 'Braintree_AddOnGateway'); diff --git a/lib/Braintree/Address.php b/lib/Braintree/Address.php index 7b6920e..800c656 100644 --- a/lib/Braintree/Address.php +++ b/lib/Braintree/Address.php @@ -3,7 +3,6 @@ /** * Braintree Address module - * PHP Version 5 * Creates and manages Braintree Addresses * * An Address belongs to a Customer. It can be associated to a @@ -14,7 +13,7 @@ * * @property-read string $company * @property-read string $countryName - * @property-read string $createdAt + * @property-read \DateTime $createdAt * @property-read string $customerId * @property-read string $extendedAddress * @property-read string $firstName @@ -24,7 +23,7 @@ * @property-read string $postalCode * @property-read string $region * @property-read string $streetAddress - * @property-read string $updatedAt + * @property-read \DateTime $updatedAt */ class Address extends Base { @@ -147,4 +146,3 @@ public static function updateNoValidate($customerOrId, $addressId, $attributes) return Configuration::gateway()->address()->updateNoValidate($customerOrId, $addressId, $attributes); } } -class_alias('Braintree\Address', 'Braintree_Address'); diff --git a/lib/Braintree/AddressGateway.php b/lib/Braintree/AddressGateway.php index a0256c0..dab79ed 100644 --- a/lib/Braintree/AddressGateway.php +++ b/lib/Braintree/AddressGateway.php @@ -5,7 +5,6 @@ /** * Braintree AddressGateway module - * PHP Version 5 * Creates and manages Braintree Addresses * * An Address belongs to a Customer. It can be associated to a @@ -205,7 +204,6 @@ public static function createSignature() */ public static function updateSignature() { - // TODO: remove customerId from update signature return self::createSignature(); } @@ -311,4 +309,3 @@ private function _verifyGatewayResponse($response) } } -class_alias('Braintree\AddressGateway', 'Braintree_AddressGateway'); diff --git a/lib/Braintree/AmexExpressCheckoutCard.php b/lib/Braintree/AmexExpressCheckoutCard.php index 0185ec2..4ddc55b 100644 --- a/lib/Braintree/AmexExpressCheckoutCard.php +++ b/lib/Braintree/AmexExpressCheckoutCard.php @@ -12,19 +12,20 @@ * @package Braintree * @category Resources * - * @property-read string $createdAt - * @property-read string $default - * @property-read string $updatedAt - * @property-read string $customerId - * @property-read string $cardType * @property-read string $bin * @property-read string $cardMemberExpiryDate * @property-read string $cardMemberNumber - * @property-read string $sourceDescription - * @property-read string $token - * @property-read string $imageUrl + * @property-read string $cardType + * @property-read \DateTime $createdAt + * @property-read string $customerId + * @property-read boolean $default * @property-read string $expirationMonth * @property-read string $expirationYear + * @property-read string $imageUrl + * @property-read string $token + * @property-read string $sourceDescription + * @property-read \Braintree\Subscription[] $subscriptions + * @property-read \DateTime $updatedAt */ class AmexExpressCheckoutCard extends Base { @@ -76,4 +77,3 @@ protected function _initialize($amexExpressCheckoutCardAttribs) $this->_set('subscriptions', $subscriptionArray); } } -class_alias('Braintree\AmexExpressCheckoutCard', 'Braintree_AmexExpressCheckoutCard'); diff --git a/lib/Braintree/AndroidPayCard.php b/lib/Braintree/AndroidPayCard.php index 50aae2d..6b2b36e 100644 --- a/lib/Braintree/AndroidPayCard.php +++ b/lib/Braintree/AndroidPayCard.php @@ -14,19 +14,21 @@ * * @property-read string $bin * @property-read string $cardType - * @property-read string $createdAt + * @property-read \DateTime $createdAt * @property-read string $customerId - * @property-read string $default + * @property-read boolean $default * @property-read string $expirationMonth * @property-read string $expirationYear * @property-read string $googleTransactionId * @property-read string $imageUrl + * @property-read boolean $isNetworkTokenized * @property-read string $last4 * @property-read string $sourceCardLast4 * @property-read string $sourceCardType * @property-read string $sourceDescription + * @property-read \Braintree\Subscription[] $subscriptions * @property-read string $token - * @property-read string $updatedAt + * @property-read \DateTime $updatedAt * @property-read string $virtualCardLast4 * @property-read string $virtualCardType */ @@ -86,4 +88,3 @@ protected function _initialize($androidPayCardAttribs) $this->_set('subscriptions', $subscriptionArray); } } -class_alias('Braintree\AndroidPayCard', 'Braintree_AndroidPayCard'); diff --git a/lib/Braintree/ApplePayCard.php b/lib/Braintree/ApplePayCard.php index 022bf7b..715cd66 100644 --- a/lib/Braintree/ApplePayCard.php +++ b/lib/Braintree/ApplePayCard.php @@ -14,17 +14,20 @@ * * @property-read string $bin * @property-read string $cardType - * @property-read string $createdAt + * @property-read \DateTime $createdAt * @property-read string $customerId + * @property-read boolean $default * @property-read string $expirationDate * @property-read string $expirationMonth * @property-read string $expirationYear + * @property-read boolean $expired * @property-read string $imageUrl * @property-read string $last4 * @property-read string $token * @property-read string $paymentInstrumentName * @property-read string $sourceDescription - * @property-read string $updatedAt + * @property-read \Braintree\Subscription[] $subscriptions + * @property-read \DateTime $updatedAt */ class ApplePayCard extends Base { @@ -97,4 +100,3 @@ protected function _initialize($applePayCardAttribs) $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear); } } -class_alias('Braintree\ApplePayCard', 'Braintree_ApplePayCard'); diff --git a/lib/Braintree/ApplePayGateway.php b/lib/Braintree/ApplePayGateway.php index c8291be..9ad587a 100644 --- a/lib/Braintree/ApplePayGateway.php +++ b/lib/Braintree/ApplePayGateway.php @@ -62,4 +62,3 @@ public function registeredDomains() } } } -class_alias('Braintree\ApplePayGateway', 'Braintree_ApplePayGateway'); diff --git a/lib/Braintree/ApplePayOptions.php b/lib/Braintree/ApplePayOptions.php index 40b2cef..37795e7 100644 --- a/lib/Braintree/ApplePayOptions.php +++ b/lib/Braintree/ApplePayOptions.php @@ -25,4 +25,3 @@ protected function _initialize($attributes) $this->_attributes = $attributes; } } -class_alias('Braintree\ApplePayOptions', 'Braintree_ApplePayOptions'); diff --git a/lib/Braintree/AuthorizationAdjustment.php b/lib/Braintree/AuthorizationAdjustment.php index f8c14ba..70c5dae 100644 --- a/lib/Braintree/AuthorizationAdjustment.php +++ b/lib/Braintree/AuthorizationAdjustment.php @@ -7,8 +7,8 @@ * @package Braintree * * @property-read string $amount - * @property-read DateTime $timestamp * @property-read boolean $success + * @property-read \DateTime $timestamp * */ @@ -32,4 +32,3 @@ public function __toString() return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']'; } } -class_alias('Braintree\AuthorizationAdjustment', 'Braintree_Authorization_Adjustment'); diff --git a/lib/Braintree/Base.php b/lib/Braintree/Base.php index 8e027c7..98d9460 100644 --- a/lib/Braintree/Base.php +++ b/lib/Braintree/Base.php @@ -9,7 +9,6 @@ * Braintree base class and initialization * Provides methods to child classes. This class cannot be instantiated. * - * PHP version 5 */ abstract class Base implements JsonSerializable { @@ -42,6 +41,9 @@ protected function __clone() */ public function __get($name) { + if (isset($this->_attributes['globalId'])) { + $this->_attributes['graphQLId'] = $this->_attributes['globalId']; + } if (array_key_exists($name, $this->_attributes)) { return $this->_attributes[$name]; } @@ -52,7 +54,7 @@ public function __get($name) } /** - * Checks for the existance of a property stored in the private $_attributes property + * Checks for the existence of a property stored in the private $_attributes property * * @ignore * @param string $name diff --git a/lib/Braintree/BinData.php b/lib/Braintree/BinData.php index cd971e9..7300f35 100644 --- a/lib/Braintree/BinData.php +++ b/lib/Braintree/BinData.php @@ -1,6 +1,17 @@ clientToken()->generateWithoutCustomerIdSignature(); } } -class_alias('Braintree\ClientToken', 'Braintree_ClientToken'); diff --git a/lib/Braintree/ClientTokenGateway.php b/lib/Braintree/ClientTokenGateway.php index b2fcbf5..5628516 100644 --- a/lib/Braintree/ClientTokenGateway.php +++ b/lib/Braintree/ClientTokenGateway.php @@ -126,4 +126,3 @@ private function _verifyGatewayResponse($response) } } -class_alias('Braintree\ClientTokenGateway', 'Braintree_ClientTokenGateway'); diff --git a/lib/Braintree/CoinbaseAccount.php b/lib/Braintree/CoinbaseAccount.php deleted file mode 100644 index a93fc1c..0000000 --- a/lib/Braintree/CoinbaseAccount.php +++ /dev/null @@ -1,110 +0,0 @@ -== More information == - * - * - * @package Braintree - * @category Resources - * - * @property-read string $customerId - * @property-read string $token - * @property-read string $userId - * @property-read string $userName - * @property-read string $userEmail - */ -class CoinbaseAccount extends Base -{ - /** - * factory method: returns an instance of CoinbaseAccount - * to the requesting method, with populated properties - * - * @ignore - * @return CoinbaseAccount - */ - public static function factory($attributes) - { - $instance = new self(); - $instance->_initialize($attributes); - return $instance; - } - - /* instance methods */ - - /** - * returns false if default is null or false - * - * @return boolean - */ - public function isDefault() - { - return $this->default; - } - - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $coinbaseAccountAttribs array of coinbaseAccount data - * @return void - */ - protected function _initialize($coinbaseAccountAttribs) - { - // set the attributes - $this->_attributes = $coinbaseAccountAttribs; - - $subscriptionArray = []; - if (isset($coinbaseAccountAttribs['subscriptions'])) { - foreach ($coinbaseAccountAttribs['subscriptions'] AS $subscription) { - $subscriptionArray[] = Subscription::factory($subscription); - } - } - - $this->_set('subscriptions', $subscriptionArray); - } - - /** - * create a printable representation of the object as: - * ClassName[property=value, property=value] - * @return string - */ - public function __toString() - { - return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) .']'; - } - - - // static methods redirecting to gateway - - public static function find($token) - { - return Configuration::gateway()->coinbaseAccount()->find($token); - } - - public static function update($token, $attributes) - { - return Configuration::gateway()->coinbaseAccount()->update($token, $attributes); - } - - public static function delete($token) - { - return Configuration::gateway()->coinbaseAccount()->delete($token); - } - - public static function sale($token, $transactionAttribs) - { - return Configuration::gateway()->coinbaseAccount()->sale($token, $transactionAttribs); - } -} -class_alias('Braintree\CoinbaseAccount', 'Braintree_CoinbaseAccount'); diff --git a/lib/Braintree/Collection.php b/lib/Braintree/Collection.php index 1cbec1d..4c66b7e 100644 --- a/lib/Braintree/Collection.php +++ b/lib/Braintree/Collection.php @@ -10,8 +10,6 @@ /** * Braintree Generic collection * - * PHP Version 5 - * * Based on Generic Collection class from: * {@link http://codeutopia.net/code/library/CU/Collection.php} * @@ -158,4 +156,3 @@ public function offsetExists($offset) } } -class_alias('Braintree\Collection', 'Braintree_Collection'); diff --git a/lib/Braintree/Configuration.php b/lib/Braintree/Configuration.php index b72c30b..a109653 100644 --- a/lib/Braintree/Configuration.php +++ b/lib/Braintree/Configuration.php @@ -33,7 +33,7 @@ class Configuration * Braintree API version to use * @access public */ - const API_VERSION = 5; + const API_VERSION = 6; const GRAPHQL_API_VERSION = '2018-09-10'; public function __construct($attribs = []) @@ -602,28 +602,6 @@ public function graphQLServerName() return $graphQLServerName; } - public function authUrl() - { - switch($this->_environment) { - case 'production': - $serverName = 'https://auth.venmo.com'; - break; - case 'qa': - $serverName = 'https://auth.qa.venmo.com'; - break; - case 'sandbox': - $serverName = 'https://auth.sandbox.venmo.com'; - break; - case 'development': - case 'integration': - default: - $serverName = 'http://auth.venmo.dev:9292'; - break; - } - - return $serverName; - } - /** * returns boolean indicating SSL is on or off for this session, * depending on environment @@ -662,4 +640,3 @@ public function logMessage($message) } } Configuration::reset(); -class_alias('Braintree\Configuration', 'Braintree_Configuration'); diff --git a/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php index ca4e7ef..2d6c9a6 100644 --- a/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php +++ b/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php @@ -34,4 +34,3 @@ protected function _initialize($attributes) $this->_attributes = $attributes; } } -class_alias('Braintree\ConnectedMerchantPayPalStatusChanged', 'Braintree_ConnectedMerchantPayPalStatusChanged'); diff --git a/lib/Braintree/ConnectedMerchantStatusTransitioned.php b/lib/Braintree/ConnectedMerchantStatusTransitioned.php index 4614437..16dc56f 100644 --- a/lib/Braintree/ConnectedMerchantStatusTransitioned.php +++ b/lib/Braintree/ConnectedMerchantStatusTransitioned.php @@ -34,4 +34,3 @@ protected function _initialize($attributes) $this->_attributes = $attributes; } } -class_alias('Braintree\ConnectedMerchantStatusTransitioned', 'Braintree_ConnectedMerchantStatusTransitioned'); diff --git a/lib/Braintree/CredentialsParser.php b/lib/Braintree/CredentialsParser.php index 034d973..c30425c 100644 --- a/lib/Braintree/CredentialsParser.php +++ b/lib/Braintree/CredentialsParser.php @@ -144,4 +144,3 @@ public function getMerchantId() return $this->_merchantId; } } -class_alias('Braintree\CredentialsParser', 'Braintree_CredentialsParser'); diff --git a/lib/Braintree/CreditCard.php b/lib/Braintree/CreditCard.php index 5b25e61..6cdc3a2 100644 --- a/lib/Braintree/CreditCard.php +++ b/lib/Braintree/CreditCard.php @@ -13,20 +13,34 @@ * @package Braintree * @category Resources * - * @property-read string $billingAddress + * @property-read \Braintree\Address $billingAddress * @property-read string $bin * @property-read string $cardType * @property-read string $cardholderName - * @property-read string $createdAt + * @property-read string $commercial + * @property-read \DateTime $createdAt * @property-read string $customerId + * @property-read string $customerLocation + * @property-read string $debit + * @property-read boolean $default + * @property-read string $durbinRegulated * @property-read string $expirationDate * @property-read string $expirationMonth * @property-read string $expirationYear + * @property-read boolean $expired + * @property-read boolean $healthcare * @property-read string $imageUrl + * @property-read string $issuingBank * @property-read string $last4 * @property-read string $maskedNumber + * @property-read string $payroll + * @property-read string $prepaid + * @property-read string $productId + * @property-read \Braintree\Subscription[] $subscriptions * @property-read string $token - * @property-read string $updatedAt + * @property-read string $uniqueNumberIdentifier + * @property-read \DateTime $updatedAt + * @property-read \Braintree\CreditCardVerification|null $verification */ class CreditCard extends Base { @@ -209,11 +223,6 @@ public static function createNoValidate($attribs) return Configuration::gateway()->creditCard()->createNoValidate($attribs); } - public static function createFromTransparentRedirect($queryString) - { - return Configuration::gateway()->creditCard()->createFromTransparentRedirect($queryString); - } - public static function createCreditCardUrl() { return Configuration::gateway()->creditCard()->createCreditCardUrl(); @@ -284,11 +293,6 @@ public static function updateCreditCardUrl() return Configuration::gateway()->creditCard()->updateCreditCardUrl(); } - public static function updateFromTransparentRedirect($queryString) - { - return Configuration::gateway()->creditCard()->updateFromTransparentRedirect($queryString); - } - public static function delete($token) { return Configuration::gateway()->creditCard()->delete($token); @@ -315,4 +319,3 @@ public static function allCardTypes() ]; } } -class_alias('Braintree\CreditCard', 'Braintree_CreditCard'); diff --git a/lib/Braintree/CreditCardGateway.php b/lib/Braintree/CreditCardGateway.php index 5f8ce04..404b4be 100644 --- a/lib/Braintree/CreditCardGateway.php +++ b/lib/Braintree/CreditCardGateway.php @@ -49,40 +49,6 @@ public function createNoValidate($attribs) $result = $this->create($attribs); return Util::returnObjectOrThrowException(__CLASS__, $result); } - /** - * create a customer from a TransparentRedirect operation - * - * @deprecated since version 2.3.0 - * @access public - * @param array $attribs - * @return Result\Successful|Result\Error - */ - public function createFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return $this->_doCreate( - '/payment_methods/all/confirm_transparent_redirect_request', - ['id' => $params['id']] - ); - } - - /** - * - * @deprecated since version 2.3.0 - * @access public - * @param none - * @return string - */ - public function createCreditCardUrl() - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); - return $this->_config->baseUrl() . $this->_config->merchantPath(). - '/payment_methods/all/create_via_transparent_redirect_request'; - } - /** * returns a ResourceCollection of expired credit cards * @return ResourceCollection @@ -292,39 +258,6 @@ public function updateNoValidate($token, $attributes) $result = $this->update($token, $attributes); return Util::returnObjectOrThrowException(__CLASS__, $result); } - /** - * - * @access public - * @param none - * @return string - */ - public function updateCreditCardUrl() - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); - return $this->_config->baseUrl() . $this->_config->merchantPath() . - '/payment_methods/all/update_via_transparent_redirect_request'; - } - - /** - * update a customer from a TransparentRedirect operation - * - * @deprecated since version 2.3.0 - * @access public - * @param array $attribs - * @return object - */ - public function updateFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return $this->_doUpdate( - 'post', - '/payment_methods/all/confirm_transparent_redirect_request', - ['id' => $params['id']] - ); - } public function delete($token) { @@ -336,7 +269,7 @@ public function delete($token) private static function baseOptions() { - return ['makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession']; + return ['makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'verificationAccountType', 'venmoSdkSession']; } private static function baseSignature($options) @@ -483,4 +416,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\CreditCardGateway', 'Braintree_CreditCardGateway'); diff --git a/lib/Braintree/CreditCardVerification.php b/lib/Braintree/CreditCardVerification.php index ab9075c..5080dda 100644 --- a/lib/Braintree/CreditCardVerification.php +++ b/lib/Braintree/CreditCardVerification.php @@ -1,6 +1,32 @@ ['amount', 'merchantAccountId']], + ['options' => ['amount', 'merchantAccountId', 'accountType']], ['creditCard' => [ 'cardholderName', 'cvv', 'number', @@ -40,4 +66,3 @@ public static function createSignature() ]]; } } -class_alias('Braintree\CreditCardVerification', 'Braintree_CreditCardVerification'); diff --git a/lib/Braintree/CreditCardVerificationGateway.php b/lib/Braintree/CreditCardVerificationGateway.php index 869bd61..47b6174 100644 --- a/lib/Braintree/CreditCardVerificationGateway.php +++ b/lib/Braintree/CreditCardVerificationGateway.php @@ -71,4 +71,3 @@ public function search($query) return new ResourceCollection($response, $pager); } } -class_alias('Braintree\CreditCardVerificationGateway', 'Braintree_CreditCardVerificationGateway'); diff --git a/lib/Braintree/CreditCardVerificationSearch.php b/lib/Braintree/CreditCardVerificationSearch.php index 2dadff9..70a2813 100644 --- a/lib/Braintree/CreditCardVerificationSearch.php +++ b/lib/Braintree/CreditCardVerificationSearch.php @@ -53,4 +53,3 @@ public static function status() return new MultipleValueNode("status", Result\CreditCardVerification::allStatuses()); } } -class_alias('Braintree\CreditCardVerificationSearch', 'Braintree_CreditCardVerificationSearch'); diff --git a/lib/Braintree/Customer.php b/lib/Braintree/Customer.php index bb9884e..c6482df 100644 --- a/lib/Braintree/Customer.php +++ b/lib/Braintree/Customer.php @@ -12,28 +12,29 @@ * @package Braintree * @category Resources * - * @property-read array $addresses - * @property-read array $paymentMethods + * @property-read \Braintree\Address[] $addresses + * @property-read \Braintree\AndroidPayCard[] $androidPayCards + * @property-read \Braintree\AmexExpressCheckoutCard[] $amexExpressCheckoutCards + * @property-read \Braintree\ApplePayCard[] $applePayCards * @property-read string $company - * @property-read string $createdAt - * @property-read array $creditCards - * @property-read array $paypalAccounts - * @property-read array $applePayCards - * @property-read array $androidPayCards - * @property-read array $amexExpressCheckoutCards - * @property-read array $venmoAccounts - * @property-read array $visaCheckoutCards - * @property-read array $masterpassCards - * @property-read array $samsungPayCards - * @property-read array $coinbaseAccounts + * @property-read \DateTime $createdAt + * @property-read \Braintree\CreditCard[] $creditCards * @property-read array $customFields custom fields passed with the request * @property-read string $email * @property-read string $fax * @property-read string $firstName + * @property-read string $graphQLId * @property-read string $id * @property-read string $lastName + * @property-read \Braintree\MasterpassCard[] $masterpassCards + * @property-read \Braintree\PaymentMethod[] $paymentMethods + * @property-read \Braintree\PayPalAccount[] $paypalAccounts * @property-read string $phone - * @property-read string $updatedAt + * @property-read \Braintree\SamsungPayCard[] $samsungPayCards + * @property-read \DateTime $updatedAt + * @property-read \Braintree\UsBankAccount[] $usBankAccounts + * @property-read \Braintree\VenmoAccount[] $venmoAccounts + * @property-read \Braintree\VisaCheckoutCard[] $visaCheckoutCards * @property-read string $website */ class Customer extends Base @@ -49,7 +50,7 @@ public static function all() /** * - * @param string $query + * @param array $query * @param int[] $ids * @return Customer|Customer[] */ @@ -78,25 +79,6 @@ public static function createNoValidate($attribs = []) return Configuration::gateway()->customer()->createNoValidate($attribs); } - /** - * @deprecated since version 2.3.0 - * @param string $queryString - * @return Result\Successful - */ - public static function createFromTransparentRedirect($queryString) - { - return Configuration::gateway()->customer()->createFromTransparentRedirect($queryString); - } - - /** - * @deprecated since version 2.3.0 - * @return string - */ - public static function createCustomerUrl() - { - return Configuration::gateway()->customer()->createCustomerUrl(); - } - /** * * @throws Exception\NotFound @@ -167,7 +149,7 @@ public static function saleNoValidate($customerId, $transactionAttribs) /** * * @throws InvalidArgumentException - * @param string $query + * @param array $query * @return ResourceCollection */ public static function search($query) @@ -199,27 +181,6 @@ public static function updateNoValidate($customerId, $attributes) return Configuration::gateway()->customer()->updateNoValidate($customerId, $attributes); } - /** - * - * @deprecated since version 2.3.0 - * @return string - */ - public static function updateCustomerUrl() - { - return Configuration::gateway()->customer()->updateCustomerUrl(); - } - - /** - * - * @deprecated since version 2.3.0 - * @param string $queryString - * @return Result\Successful|Result\Error - */ - public static function updateFromTransparentRedirect($queryString) - { - return Configuration::gateway()->customer()->updateFromTransparentRedirect($queryString); - } - /* instance methods */ /** @@ -250,14 +211,6 @@ protected function _initialize($customerAttribs) } $this->_set('creditCards', $creditCardArray); - $coinbaseAccountArray = []; - if (isset($customerAttribs['coinbaseAccounts'])) { - foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) { - $coinbaseAccountArray[] = CoinbaseAccount::factory($coinbaseAccount); - } - } - $this->_set('coinbaseAccounts', $coinbaseAccountArray); - $paypalAccountArray = []; if (isset($customerAttribs['paypalAccounts'])) { foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { @@ -334,7 +287,6 @@ protected function _initialize($customerAttribs) $this->creditCards, $this->paypalAccounts, $this->applePayCards, - $this->coinbaseAccounts, $this->androidPayCards, $this->amexExpressCheckoutCards, $this->venmoAccounts, @@ -343,6 +295,12 @@ protected function _initialize($customerAttribs) $this->samsungPayCards, $this->usBankAccounts )); + + $customFields = []; + if (isset($customerAttribs['customFields'])) { + $customFields = $customerAttribs['customFields']; + } + $this->_set('customFields', $customFields); } /** @@ -367,18 +325,6 @@ public function isEqual($otherCust) return !($otherCust instanceof Customer) ? false : $this->id === $otherCust->id; } - /** - * returns an array containt all of the customer's payment methods - * - * @deprecated since version 3.1.0 - use the paymentMethods property directly - * - * @return array - */ - public function paymentMethods() - { - return $this->paymentMethods; - } - /** * returns the customer's default payment method * @@ -431,4 +377,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\Customer', 'Braintree_Customer'); diff --git a/lib/Braintree/CustomerGateway.php b/lib/Braintree/CustomerGateway.php index 3834509..25d7461 100644 --- a/lib/Braintree/CustomerGateway.php +++ b/lib/Braintree/CustomerGateway.php @@ -102,40 +102,6 @@ public function createNoValidate($attribs = []) $result = $this->create($attribs); return Util::returnObjectOrThrowException(__CLASS__, $result); } - /** - * create a customer from a TransparentRedirect operation - * - * @deprecated since version 2.3.0 - * @access public - * @param array $attribs - * @return Customer - */ - public function createFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return $this->_doCreate( - '/customers/all/confirm_transparent_redirect_request', - ['id' => $params['id']] - ); - } - - /** - * - * @deprecated since version 2.3.0 - * @access public - * @param none - * @return string - */ - public function createCustomerUrl() - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); - return $this->_config->baseUrl() . $this->_config->merchantPath() . - '/customers/all/create_via_transparent_redirect_request'; - } - /** * creates a full array signature of a valid create request @@ -202,6 +168,12 @@ public static function updateSignature() ['paypal' => [ 'payee_email', 'payeeEmail', + 'order_id', + 'orderId', + 'custom_field', + 'customField', + 'description', + 'amount', ['shipping' => [ 'firstName', 'lastName', 'company', 'countryName', @@ -400,39 +372,6 @@ public function updateNoValidate($customerId, $attributes) $result = $this->update($customerId, $attributes); return Util::returnObjectOrThrowException(__CLASS__, $result); } - /** - * - * @deprecated since version 2.3.0 - * @access public - * @return string - */ - public function updateCustomerUrl() - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); - return $this->_config->baseUrl() . $this->_config->merchantPath() . - '/customers/all/update_via_transparent_redirect_request'; - } - - /** - * update a customer from a TransparentRedirect operation - * - * @deprecated since version 2.3.0 - * @access public - * @param string $queryString - * @return object - */ - public function updateFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return $this->_doUpdate( - 'post', - '/customers/all/confirm_transparent_redirect_request', - ['id' => $params['id']] - ); - } /* instance methods */ @@ -468,15 +407,6 @@ protected function _initialize($customerAttribs) } $this->_set('creditCards', $creditCardArray); - // map each coinbaseAccount into its own object - $coinbaseAccountArray = []; - if (isset($customerAttribs['coinbaseAccounts'])) { - foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) { - $coinbaseAccountArray[] = CoinbaseAccount::factory($coinbaseAccount); - } - } - $this->_set('coinbaseAccounts', $coinbaseAccountArray); - // map each paypalAccount into its own object $paypalAccountArray = []; if (isset($customerAttribs['paypalAccounts'])) { @@ -504,7 +434,7 @@ protected function _initialize($customerAttribs) } $this->_set('androidPayCards', $androidPayCardArray); - $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts, $this->androidPayCards)); + $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->androidPayCards)); } /** @@ -659,4 +589,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\CustomerGateway', 'Braintree_CustomerGateway'); diff --git a/lib/Braintree/CustomerSearch.php b/lib/Braintree/CustomerSearch.php index 3bc734e..8893aec 100644 --- a/lib/Braintree/CustomerSearch.php +++ b/lib/Braintree/CustomerSearch.php @@ -31,4 +31,3 @@ public static function ids() { return new MultipleV public static function createdAt() { return new RangeNode("created_at"); } } -class_alias('Braintree\CustomerSearch', 'Braintree_CustomerSearch'); diff --git a/lib/Braintree/Descriptor.php b/lib/Braintree/Descriptor.php index d63383f..cc0b697 100644 --- a/lib/Braintree/Descriptor.php +++ b/lib/Braintree/Descriptor.php @@ -1,7 +1,11 @@ disbursementType == Disbursement::TYPE_CREDIT; } } -class_alias('Braintree\Disbursement', 'Braintree_Disbursement'); diff --git a/lib/Braintree/DisbursementDetails.php b/lib/Braintree/DisbursementDetails.php index ffc31e8..69b656c 100644 --- a/lib/Braintree/DisbursementDetails.php +++ b/lib/Braintree/DisbursementDetails.php @@ -8,12 +8,12 @@ * * @package Braintree * + * @property-read string $disbursementDate + * @property-read boolean $fundsHeld * @property-read string $settlementAmount - * @property-read string $settlementCurrencyIsoCode * @property-read string $settlementCurrencyExchangeRate - * @property-read string $fundsHeld + * @property-read string $settlementCurrencyIsoCode * @property-read string $success - * @property-read string $disbursementDate */ class DisbursementDetails extends Instance { @@ -21,4 +21,3 @@ public function isValid() { return !is_null($this->disbursementDate); } } -class_alias('Braintree\DisbursementDetails', 'Braintree_DisbursementDetails'); diff --git a/lib/Braintree/Discount.php b/lib/Braintree/Discount.php index da780d0..f761e20 100644 --- a/lib/Braintree/Discount.php +++ b/lib/Braintree/Discount.php @@ -1,6 +1,20 @@ discount()->all(); } } -class_alias('Braintree\Discount', 'Braintree_Discount'); diff --git a/lib/Braintree/DiscountGateway.php b/lib/Braintree/DiscountGateway.php index d26672a..249a1e8 100644 --- a/lib/Braintree/DiscountGateway.php +++ b/lib/Braintree/DiscountGateway.php @@ -28,4 +28,3 @@ public function all() ); } } -class_alias('Braintree\DiscountGateway', 'Braintree_DiscountGateway'); diff --git a/lib/Braintree/Dispute.php b/lib/Braintree/Dispute.php index dc17eba..3d9e825 100644 --- a/lib/Braintree/Dispute.php +++ b/lib/Braintree/Dispute.php @@ -8,12 +8,27 @@ * @package Braintree * * @property-read string $amount + * @property-read \DateTime $createdAt * @property-read string $currencyIsoCode - * @property-read date $receivedDate + * @property-read string $disbursementDate + * @property-read \Braintree\Dispute\EvidenceDetails $evidence + * @property-read string $graphQLId + * @property-read string $id + * @property-read string $kind + * @property-read string $merchantAccountId + * @property-read string $originalDisputeId + * @property-read string $processorComments * @property-read string $reason + * @property-read string $reasonCode + * @property-read string $reasonDescription + * @property-read \DateTime $receivedDate + * @property-read string $referenceNumber + * @property-read \DateTime $replyByDate * @property-read string $status - * @property-read string $disbursementDate - * @property-read object $transactionDetails + * @property-read \Braintree\Dispute\StatusHistoryDetails[] $statusHistory + * @property-read \Braintree\Dispute\TransactionDetails $transaction + * @property-read \Braintree\Dispute\TransactionDetails $transactionDetails + * @property-read \DateTime $updatedAt */ class Dispute extends Base { @@ -27,9 +42,6 @@ class Dispute extends Base const WON = 'won'; const LOST = 'lost'; - /* deprecated; for backwards compatibilty */ - const Open = 'open'; - /* Dispute Reason */ const CANCELLED_RECURRING_TRANSACTION = "cancelled_recurring_transaction"; const CREDIT_NOT_PROCESSED = "credit_not_processed"; @@ -174,4 +186,3 @@ public static function search($query) return Configuration::gateway()->dispute()->search($query); } } -class_alias('Braintree\Dispute', 'Braintree_Dispute'); diff --git a/lib/Braintree/Dispute/EvidenceDetails.php b/lib/Braintree/Dispute/EvidenceDetails.php index 14fa9d2..140b841 100644 --- a/lib/Braintree/Dispute/EvidenceDetails.php +++ b/lib/Braintree/Dispute/EvidenceDetails.php @@ -10,12 +10,12 @@ * * @property-read string $category * @property-read string $comment - * @property-read date $created_at + * @property-read \DateTime $createdAt * @property-read string $id - * @property-read string $sent_to_processor_at - * @property-read string $url - * @property-read string $tag + * @property-read \DateTime $sentToProcessorAt * @property-read string $sequenceNumber + * @property-read string $tag + * @property-read string $url */ class EvidenceDetails extends Instance { @@ -27,5 +27,3 @@ public function __construct($attributes) parent::__construct($attributes); } } - -class_alias('Braintree\Dispute\EvidenceDetails', 'Braintree_Dispute_EvidenceDetails'); diff --git a/lib/Braintree/Dispute/StatusHistoryDetails.php b/lib/Braintree/Dispute/StatusHistoryDetails.php index 18e32b9..e724e85 100644 --- a/lib/Braintree/Dispute/StatusHistoryDetails.php +++ b/lib/Braintree/Dispute/StatusHistoryDetails.php @@ -8,13 +8,11 @@ * * @package Braintree * - * @property-read string $effective_date - * @property-read string $disbursement_date + * @property-read \DateTime $disbursementDate + * @property-read \DateTime $effectiveDate * @property-read string $status - * @property-read date $timestamp + * @property-read \DateTime $timestamp */ class StatusHistoryDetails extends Instance { } - -class_alias('Braintree\Dispute\StatusHistoryDetails', 'Braintree_Dispute_StatusHistoryDetails'); diff --git a/lib/Braintree/Dispute/TransactionDetails.php b/lib/Braintree/Dispute/TransactionDetails.php index 313f77c..b25860a 100644 --- a/lib/Braintree/Dispute/TransactionDetails.php +++ b/lib/Braintree/Dispute/TransactionDetails.php @@ -21,5 +21,3 @@ class TransactionDetails extends Instance { } - -class_alias('Braintree\Dispute\TransactionDetails', 'Braintree_Dispute_TransactionDetails'); diff --git a/lib/Braintree/DisputeGateway.php b/lib/Braintree/DisputeGateway.php index 72d7383..34b0737 100644 --- a/lib/Braintree/DisputeGateway.php +++ b/lib/Braintree/DisputeGateway.php @@ -5,7 +5,6 @@ /** * Braintree DisputeGateway module - * PHP Version 5 * Creates and manages Braintree Disputes * * @package Braintree @@ -271,4 +270,3 @@ public function fetchDisputes($query, $page) return new PaginatedResult($totalItems, $pageSize, $disputes); } } -class_alias('Braintree\DisputeGateway', 'Braintree_DisputeGateway'); diff --git a/lib/Braintree/DisputeSearch.php b/lib/Braintree/DisputeSearch.php index b97c463..ce99727 100644 --- a/lib/Braintree/DisputeSearch.php +++ b/lib/Braintree/DisputeSearch.php @@ -87,4 +87,3 @@ public static function transactionSource() return new MultipleValueNode("transaction_source"); } } -class_alias('Braintree\DisputeSearch', 'Braintree_DisputeSearch'); diff --git a/lib/Braintree/DocumentUpload.php b/lib/Braintree/DocumentUpload.php index 50af05c..1bf4709 100644 --- a/lib/Braintree/DocumentUpload.php +++ b/lib/Braintree/DocumentUpload.php @@ -13,6 +13,13 @@ * ]); * * For more information on DocumentUploads, see https://developers.braintreepayments.com/reference/request/document_upload/create + * + * @property-read string $contentType + * @property-read \DateTime $expiresAt + * @property-read string $id + * @property-read string $kind + * @property-read string $name + * @property-read int $size */ class DocumentUpload extends Base { @@ -42,4 +49,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\DocumentUpload', 'Braintree_DocumentUpload'); diff --git a/lib/Braintree/DocumentUploadGateway.php b/lib/Braintree/DocumentUploadGateway.php index 2839968..ea17467 100644 --- a/lib/Braintree/DocumentUploadGateway.php +++ b/lib/Braintree/DocumentUploadGateway.php @@ -5,7 +5,6 @@ /** * Braintree DisputeGateway module - * PHP Version 5 * Creates and manages Braintree Disputes * * @package Braintree @@ -78,4 +77,3 @@ public static function createSignature() ]; } } -class_alias('Braintree\DocumentUploadGateway', 'Braintree_DocumentUploadGateway'); diff --git a/lib/Braintree/EndsWithNode.php b/lib/Braintree/EndsWithNode.php index edccec2..1bb5a20 100644 --- a/lib/Braintree/EndsWithNode.php +++ b/lib/Braintree/EndsWithNode.php @@ -20,4 +20,3 @@ public function toParam() return $this->searchTerms; } } -class_alias('Braintree\EndsWithNode', 'Braintree_EndsWithNode'); diff --git a/lib/Braintree/EqualityNode.php b/lib/Braintree/EqualityNode.php index d91e1eb..a56637f 100644 --- a/lib/Braintree/EqualityNode.php +++ b/lib/Braintree/EqualityNode.php @@ -9,4 +9,3 @@ function isNot($value) return $this; } } -class_alias('Braintree\EqualityNode', 'Braintree_EqualityNode'); diff --git a/lib/Braintree/Error/Codes.php b/lib/Braintree/Error/Codes.php index 5441a5c..391688f 100644 --- a/lib/Braintree/Error/Codes.php +++ b/lib/Braintree/Error/Codes.php @@ -17,33 +17,34 @@ */ class Codes { - const ADDRESS_CANNOT_BE_BLANK = '81801'; - const ADDRESS_COMPANY_IS_INVALID = '91821'; - const ADDRESS_COMPANY_IS_TOO_LONG = '81802'; - const ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED = '91814'; - const ADDRESS_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED = '91816'; - const ADDRESS_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED = '91817'; - const ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED = '91803'; - const ADDRESS_EXTENDED_ADDRESS_IS_INVALID = '91823'; - const ADDRESS_EXTENDED_ADDRESS_IS_TOO_LONG = '81804'; - const ADDRESS_FIRST_NAME_IS_INVALID = '91819'; - const ADDRESS_FIRST_NAME_IS_TOO_LONG = '81805'; - const ADDRESS_INCONSISTENT_COUNTRY = '91815'; - const ADDRESS_LAST_NAME_IS_INVALID = '91820'; - const ADDRESS_LAST_NAME_IS_TOO_LONG = '81806'; - const ADDRESS_LOCALITY_IS_INVALID = '91824'; - const ADDRESS_LOCALITY_IS_TOO_LONG = '81807'; - const ADDRESS_POSTAL_CODE_INVALID_CHARACTERS = '81813'; - const ADDRESS_POSTAL_CODE_IS_INVALID = '91826'; - const ADDRESS_POSTAL_CODE_IS_REQUIRED = '81808'; - const ADDRESS_POSTAL_CODE_IS_TOO_LONG = '81809'; - const ADDRESS_REGION_IS_INVALID = '91825'; - const ADDRESS_REGION_IS_TOO_LONG = '81810'; - const ADDRESS_STATE_IS_INVALID_FOR_SELLER_PROTECTION = '81827'; - const ADDRESS_STREET_ADDRESS_IS_INVALID = '91822'; - const ADDRESS_STREET_ADDRESS_IS_REQUIRED = '81811'; - const ADDRESS_STREET_ADDRESS_IS_TOO_LONG = '81812'; - const ADDRESS_TOO_MANY_ADDRESSES_PER_CUSTOMER = '91818'; + const ADDRESS_CANNOT_BE_BLANK = '81801'; + const ADDRESS_COMPANY_IS_INVALID = '91821'; + const ADDRESS_COMPANY_IS_TOO_LONG = '81802'; + const ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED = '91814'; + const ADDRESS_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED = '91816'; + const ADDRESS_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED = '91817'; + const ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED = '91803'; + const ADDRESS_EXTENDED_ADDRESS_IS_INVALID = '91823'; + const ADDRESS_EXTENDED_ADDRESS_IS_TOO_LONG = '81804'; + const ADDRESS_FIRST_NAME_IS_INVALID = '91819'; + const ADDRESS_FIRST_NAME_IS_TOO_LONG = '81805'; + const ADDRESS_INCONSISTENT_COUNTRY = '91815'; + const ADDRESS_LAST_NAME_IS_INVALID = '91820'; + const ADDRESS_LAST_NAME_IS_TOO_LONG = '81806'; + const ADDRESS_LOCALITY_IS_INVALID = '91824'; + const ADDRESS_LOCALITY_IS_TOO_LONG = '81807'; + const ADDRESS_POSTAL_CODE_INVALID_CHARACTERS = '81813'; + const ADDRESS_POSTAL_CODE_IS_INVALID = '91826'; + const ADDRESS_POSTAL_CODE_IS_REQUIRED = '81808'; + const ADDRESS_POSTAL_CODE_IS_REQUIRED_FOR_CARD_BRAND_AND_PROCESSOR = '81828'; + const ADDRESS_POSTAL_CODE_IS_TOO_LONG = '81809'; + const ADDRESS_REGION_IS_INVALID = '91825'; + const ADDRESS_REGION_IS_TOO_LONG = '81810'; + const ADDRESS_STATE_IS_INVALID_FOR_SELLER_PROTECTION = '81827'; + const ADDRESS_STREET_ADDRESS_IS_INVALID = '91822'; + const ADDRESS_STREET_ADDRESS_IS_REQUIRED = '81811'; + const ADDRESS_STREET_ADDRESS_IS_TOO_LONG = '81812'; + const ADDRESS_TOO_MANY_ADDRESSES_PER_CUSTOMER = '91818'; const APPLE_PAY_CARDS_ARE_NOT_ACCEPTED = '83501'; const APPLE_PAY_CUSTOMER_ID_IS_REQUIRED_FOR_VAULTING = '83502'; @@ -121,6 +122,8 @@ class Codes const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_IS_FORBIDDEN = '91743'; const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_IS_SUSPENDED = '91742'; const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_CANNOT_BE_SUB_MERCHANT_ACCOUNT = '91755'; + const CREDIT_CARD_OPTIONS_VERIFICATION_ACCOUNT_TYPE_IS_INVALID = '91757'; + const CREDIT_CARD_OPTIONS_VERIFICATION_ACCOUNT_TYPE_NOT_SUPPORTED = '91758'; const CREDIT_CARD_PAYMENT_METHOD_CONFLICT = '81725'; const CREDIT_CARD_PAYMENT_METHOD_IS_NOT_A_CREDIT_CARD = '91738'; const CREDIT_CARD_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91734'; @@ -195,30 +198,86 @@ class Codes const DOCUMENT_UPLOAD_FILE_IS_TOO_LARGE = '84902'; const DOCUMENT_UPLOAD_FILE_TYPE_IS_INVALID = '84903'; const DOCUMENT_UPLOAD_FILE_IS_MALFORMED_OR_ENCRYPTED = '84904'; + const DOCUMENT_UPLOAD_FILE_IS_TOO_LONG = '84905'; const FAILED_AUTH_ADJUSTMENT_ALLOW_RETRY = '95603'; const FAILED_AUTH_ADJUSTMENT_HARD_DECLINE = '95602'; const FINAL_AUTH_SUBMIT_FOR_SETTLEMENT_FOR_DIFFERENT_AMOUNT = '95601'; - const INDUSTRY_DATA_INDUSTRY_TYPE_IS_INVALID = '93401'; - const INDUSTRY_DATA_LODGING_EMPTY_DATA = '93402'; - const INDUSTRY_DATA_LODGING_FOLIO_NUMBER_IS_INVALID = '93403'; - const INDUSTRY_DATA_LODGING_CHECK_IN_DATE_IS_INVALID = '93404'; - const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_IS_INVALID = '93405'; - const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_MUST_FOLLOW_CHECK_IN_DATE = '93406'; - const INDUSTRY_DATA_LODGING_UNKNOWN_DATA_FIELD = '93407'; - const INDUSTRY_DATA_TRAVEL_CRUISE_EMPTY_DATA = '93408'; - const INDUSTRY_DATA_TRAVEL_CRUISE_UNKNOWN_DATA_FIELD = '93409'; - const INDUSTRY_DATA_TRAVEL_CRUISE_TRAVEL_PACKAGE_IS_INVALID = '93410'; - const INDUSTRY_DATA_TRAVEL_CRUISE_DEPARTURE_DATE_IS_INVALID = '93411'; - const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_IN_DATE_IS_INVALID = '93412'; - const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_OUT_DATE_IS_INVALID = '93413'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_ARRIVAL_AIRPORT_CODE_IS_TOO_LONG = '96301'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_ARRIVAL_TIME_FORMAT_IS_INVALID = '96302'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_CARRIER_CODE_IS_TOO_LONG = '96303'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_CONJUNCTION_TICKET_IS_TOO_LONG = '96304'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_COUPON_NUMBER_IS_TOO_LONG = '96305'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_DEPARTURE_AIRPORT_CODE_IS_TOO_LONG = '96306'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_DEPARTURE_TIME_FORMAT_IS_INVALID = '96307'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_EXCHANGE_TICKET_IS_TOO_LONG = '96308'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FARE_AMOUNT_CANNOT_BE_NEGATIVE = '96309'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FARE_AMOUNT_FORMAT_IS_INVALID = '96310'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FARE_AMOUNT_IS_TOO_LARGE = '96311'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FARE_BASIS_CODE_IS_TOO_LONG = '96312'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FEE_AMOUNT_CANNOT_BE_NEGATIVE = '96313'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FEE_AMOUNT_FORMAT_IS_INVALID = '96314'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_FEE_AMOUNT_IS_TOO_LARGE = '96315'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_SERVICE_CLASS_IS_TOO_LONG = '96316'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_TAX_AMOUNT_CANNOT_BE_NEGATIVE = '96317'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_TAX_AMOUNT_FORMAT_IS_INVALID = '96318'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_TAX_AMOUNT_IS_TOO_LARGE = '96319'; + const INDUSTRY_DATA_LEG_TRAVEL_FLIGHT_TICKET_NUMBER_IS_TOO_LONG = '96320'; + + const INDUSTRY_DATA_INDUSTRY_TYPE_IS_INVALID = '93401'; + const INDUSTRY_DATA_LODGING_EMPTY_DATA = '93402'; + const INDUSTRY_DATA_LODGING_FOLIO_NUMBER_IS_INVALID = '93403'; + const INDUSTRY_DATA_LODGING_CHECK_IN_DATE_IS_INVALID = '93404'; + const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_IS_INVALID = '93405'; + const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_MUST_FOLLOW_CHECK_IN_DATE = '93406'; + const INDUSTRY_DATA_LODGING_UNKNOWN_DATA_FIELD = '93407'; + const INDUSTRY_DATA_LODGING_ROOM_RATE_MUST_BE_GREATER_THAN_ZERO = '93433'; + const INDUSTRY_DATA_LODGING_ROOM_RATE_FORMAT_IS_INVALID = '93434'; + const INDUSTRY_DATA_LODGING_ROOM_RATE_IS_TOO_LARGE = '93435'; + const INDUSTRY_DATA_LODGING_ROOM_TAX_MUST_BE_GREATER_THAN_ZERO = '93436'; + const INDUSTRY_DATA_LODGING_ROOM_TAX_FORMAT_IS_INVALID = '93437'; + const INDUSTRY_DATA_LODGING_ROOM_TAX_IS_TOO_LARGE = '93438'; + const INDUSTRY_DATA_LODGING_NO_SHOW_INDICATOR_IS_INVALID = '93439'; + const INDUSTRY_DATA_LODGING_ADVANCED_DEPOSIT_INDICATOR_IS_INVALID = '93440'; + const INDUSTRY_DATA_LODGING_FIRE_SAFETY_INDICATOR_IS_INVALID = '93441'; + const INDUSTRY_DATA_LODGING_PROPERTY_PHONE_IS_INVALID = '93442'; + const INDUSTRY_DATA_TRAVEL_CRUISE_EMPTY_DATA = '93408'; + const INDUSTRY_DATA_TRAVEL_CRUISE_UNKNOWN_DATA_FIELD = '93409'; + const INDUSTRY_DATA_TRAVEL_CRUISE_TRAVEL_PACKAGE_IS_INVALID = '93410'; + const INDUSTRY_DATA_TRAVEL_CRUISE_DEPARTURE_DATE_IS_INVALID = '93411'; + const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_IN_DATE_IS_INVALID = '93412'; + const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_OUT_DATE_IS_INVALID = '93413'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_EMPTY_DATA = '93414'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_UNKNOWN_DATA_FIELD = '93415'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_CUSTOMER_CODE_IS_TOO_LONG = '93416'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FARE_AMOUNT_CANNOT_BE_NEGATIVE = '93417'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FARE_AMOUNT_FORMAT_IS_INVALID = '93418'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FARE_AMOUNT_IS_TOO_LARGE = '93419'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FEE_AMOUNT_CANNOT_BE_NEGATIVE = '93420'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FEE_AMOUNT_FORMAT_IS_INVALID = '93421'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_FEE_AMOUNT_IS_TOO_LARGE = '93422'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_ISSUED_DATE_FORMAT_IS_INVALID = '93423'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_ISSUING_CARRIER_CODE_IS_TOO_LONG = '93424'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_PASSENGER_MIDDLE_INITIAL_IS_TOO_LONG = '93425'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_RESTRICTED_TICKET_IS_REQUIRED = '93426'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_TAX_AMOUNT_CANNOT_BE_NEGATIVE = '93427'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_TAX_AMOUNT_FORMAT_IS_INVALID = '93428'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_TAX_AMOUNT_IS_TOO_LARGE = '93429'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_TICKET_NUMBER_IS_TOO_LONG = '93430'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_LEGS_EXPECTED = '93431'; + const INDUSTRY_DATA_TRAVEL_FLIGHT_TOO_MANY_LEGS = '93432'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_KIND_IS_INVALID = '96601'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_KIND_MUST_BE_UNIQUE = '96602'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '96603'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_AMOUNT_FORMAT_IS_INVALID = '96604'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_AMOUNT_IS_TOO_LARGE = '96605'; + const INDUSTRY_DATA_ADDITIONAL_CHARGE_AMOUNT_IS_REQUIRED = '96606'; const TRANSACTION_LINE_ITEM_COMMODITY_CODE_IS_TOO_LONG = '95801'; const TRANSACTION_LINE_ITEM_DESCRIPTION_IS_TOO_LONG = '95803'; const TRANSACTION_LINE_ITEM_DISCOUNT_AMOUNT_FORMAT_IS_INVALID = '95804'; const TRANSACTION_LINE_ITEM_DISCOUNT_AMOUNT_IS_TOO_LARGE = '95805'; - const TRANSACTION_LINE_ITEM_DISCOUNT_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '95806'; // Deprecated as the amount may be zero. Use TRANSACTION_LINE_ITEM_DISCOUNT_AMOUNT_CANNOT_BE_ZERO. const TRANSACTION_LINE_ITEM_DISCOUNT_AMOUNT_CANNOT_BE_NEGATIVE = '95806'; const TRANSACTION_LINE_ITEM_KIND_IS_INVALID = '95807'; const TRANSACTION_LINE_ITEM_KIND_IS_REQUIRED = '95808'; @@ -239,7 +298,6 @@ class Codes const TRANSACTION_LINE_ITEM_UNIT_OF_MEASURE_IS_TOO_LONG = '95821'; const TRANSACTION_LINE_ITEM_UNIT_TAX_AMOUNT_FORMAT_IS_INVALID = '95824'; const TRANSACTION_LINE_ITEM_UNIT_TAX_AMOUNT_IS_TOO_LARGE = '95825'; - const TRANSACTION_LINE_ITEM_UNIT_TAX_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '95826'; // Deprecated as the amount may be zero. Use TRANSACTION_LINE_ITEM_UNIT_TAX_AMOUNT_CANNOT_BE_ZERO. const TRANSACTION_LINE_ITEM_UNIT_TAX_AMOUNT_CANNOT_BE_NEGATIVE = '95826'; const TRANSACTION_LINE_ITEM_TAX_AMOUNT_FORMAT_IS_INVALID = '95827'; const TRANSACTION_LINE_ITEM_TAX_AMOUNT_IS_TOO_LARGE = '95828'; @@ -398,24 +456,6 @@ class Codes const PAYPAL_ACCOUNT_PAYPAL_COMMUNICATION_ERROR = '92910'; const PAYPAL_ACCOUNT_TOKEN_IS_IN_USE = '92906'; - const SEPA_BANK_ACCOUNT_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '93003'; - const SEPA_BANK_ACCOUNT_BIC_IS_REQUIRED = '93002'; - const SEPA_BANK_ACCOUNT_IBAN_IS_REQUIRED = '93001'; - - const SEPA_MANDATE_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '83301'; - const SEPA_MANDATE_BIC_INVALID_CHARACTER = '83306'; - const SEPA_MANDATE_BIC_IS_REQUIRED = '83302'; - const SEPA_MANDATE_BIC_LENGTH_IS_INVALID = '83307'; - const SEPA_MANDATE_BIC_UNSUPPORTED_COUNTRY = '83308'; - const SEPA_MANDATE_BILLING_ADDRESS_CONFLICT = '93311'; - const SEPA_MANDATE_BILLING_ADDRESS_ID_IS_INVALID = '93312'; - const SEPA_MANDATE_IBAN_INVALID_CHARACTER = '83305'; - const SEPA_MANDATE_IBAN_INVALID_FORMAT = '83310'; - const SEPA_MANDATE_IBAN_IS_REQUIRED = '83303'; - const SEPA_MANDATE_IBAN_UNSUPPORTED_COUNTRY = '83309'; - const SEPA_MANDATE_TYPE_IS_REQUIRED = '93304'; - const SEPA_MANDATE_TYPE_IS_INVALID = '93313'; - const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_INVALID = '82302'; const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_REQUIRED = '82301'; const SETTLEMENT_BATCH_SUMMARY_CUSTOM_FIELD_IS_INVALID = '82303'; @@ -485,12 +525,12 @@ class Codes const TRANSACTION_AMOUNT_CANNOT_BE_NEGATIVE = '81501'; const TRANSACTION_AMOUNT_DOES_NOT_MATCH3_D_SECURE_AMOUNT = '91585'; - const TRANSACTION_AMOUNT_DOES_NOT_MATCH_IDEAL_PAYMENT_AMOUNT = '915144'; const TRANSACTION_AMOUNT_FORMAT_IS_INVALID = '81503'; const TRANSACTION_AMOUNT_IS_INVALID = '81503'; const TRANSACTION_AMOUNT_IS_REQUIRED = '81502'; const TRANSACTION_AMOUNT_IS_TOO_LARGE = '81528'; const TRANSACTION_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '81531'; + const TRANSACTION_AMOUNT_NOT_SUPPORTED_BY_PROCESSOR = '815193'; const TRANSACTION_BILLING_ADDRESS_CONFLICT = '91530'; const TRANSACTION_CANNOT_BE_VOIDED = '91504'; const TRANSACTION_CANNOT_CANCEL_RELEASE = '91562'; @@ -521,8 +561,6 @@ class Codes const TRANSACTION_CUSTOM_FIELD_IS_TOO_LONG = '81527'; const TRANSACTION_PAYMENT_INSTRUMENT_WITH_EXTERNAL_VAULT_IS_INVALID = '915176'; const TRANSACTION_HAS_ALREADY_BEEN_REFUNDED = '91512'; - const TRANSACTION_IDEAL_PAYMENT_NOT_COMPLETE = '815141'; - const TRANSACTION_IDEAL_PAYMENTS_CANNOT_BE_VAULTED = '915150'; const TRANSACTION_LINE_ITEMS_EXPECTED = '915158'; const TRANSACTION_TOO_MANY_LINE_ITEMS = '915157'; const TRANSACTION_DISCOUNT_AMOUNT_FORMAT_IS_INVALID = '915159'; @@ -535,9 +573,9 @@ class Codes const TRANSACTION_SHIPS_FROM_POSTAL_CODE_IS_INVALID = '915166'; const TRANSACTION_SHIPS_FROM_POSTAL_CODE_INVALID_CHARACTERS = '915167'; const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_MATCH3_D_SECURE_MERCHANT_ACCOUNT = '91584'; - const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_MATCH_IDEAL_PAYMENT_MERCHANT_ACCOUNT = '915143'; const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_MOTO = '91558'; const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_REFUNDS = '91547'; + const TRANSACTION_MERCHANT_ACCOUNT_ID_DOES_NOT_MATCH_SUBSCRIPTION = '915180'; const TRANSACTION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91513'; const TRANSACTION_MERCHANT_ACCOUNT_IS_SUSPENDED = '91514'; const TRANSACTION_MERCHANT_ACCOUNT_NAME_IS_INVALID = '91513'; //Deprecated @@ -546,8 +584,9 @@ class Codes const TRANSACTION_OPTIONS_SUBMIT_FOR_SETTLEMENT_IS_REQUIRED_FOR_PAYPAL_UNILATERAL = '91582'; const TRANSACTION_OPTIONS_USE_BILLING_FOR_SHIPPING_DISABLED = '91572'; const TRANSACTION_OPTIONS_VAULT_IS_DISABLED = '91525'; - const TRANSACTION_ORDER_ID_DOES_NOT_MATCH_IDEAL_PAYMENT_ORDER_ID = '91503'; - const TRANSACTION_ORDER_ID_IS_REQUIRED_WITH_IDEAL_PAYMENT = '91502'; + const TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_IS_INVALID = '915184'; + const TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_NOT_SUPPORTED = '915185'; + const TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_DEBIT_DOES_NOT_SUPPORT_AUTHS = '915186'; const TRANSACTION_ORDER_ID_IS_TOO_LONG = '91501'; const TRANSACTION_PAYMENT_INSTRUMENT_NOT_SUPPORTED_BY_MERCHANT_ACCOUNT = '91577'; const TRANSACTION_PAYMENT_INSTRUMENT_TYPE_IS_NOT_ACCEPTED = '915101'; @@ -569,6 +608,7 @@ class Codes const TRANSACTION_PROCESSOR_AUTHORIZATION_CODE_IS_INVALID = '81520'; const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_AUTHS = '915104'; const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_CREDITS = '91546'; + const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_MOTO_FOR_CARD_TYPE = '915195'; const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_PARTIAL_SETTLEMENT = '915102'; const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_UPDATING_ORDER_ID = '915107'; const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_UPDATING_DESCRIPTOR = '915108'; @@ -577,6 +617,8 @@ class Codes const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_INVALID = '91548'; const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_TOO_LONG = '91537'; const TRANSACTION_REFUND_AMOUNT_IS_TOO_LARGE = '91521'; + const TRANSACTION_REFUND_AUTH_HARD_DECLINED = '915200'; + const TRANSACTION_REFUND_AUTH_SOFT_DECLINED = '915201'; const TRANSACTION_SERVICE_FEE_AMOUNT_CANNOT_BE_NEGATIVE = '91554'; const TRANSACTION_SERVICE_FEE_AMOUNT_FORMAT_IS_INVALID = '91555'; const TRANSACTION_SERVICE_FEE_AMOUNT_IS_TOO_LARGE = '91556'; @@ -595,13 +637,17 @@ class Codes const TRANSACTION_TAX_AMOUNT_IS_TOO_LARGE = '81536'; const TRANSACTION_THREE_D_SECURE_AUTHENTICATION_FAILED = '81571'; - const TRANSACTION_THREE_D_SECURE_TOKEN_IS_INVALID = '91568'; - const TRANSACTION_THREE_D_SECURE_TRANSACTION_DATA_DOESNT_MATCH_VERIFY = '91570'; - const TRANSACTION_THREE_D_SECURE_ECI_FLAG_IS_REQUIRED = '915113'; + const TRANSACTION_THREE_D_SECURE_AUTHENTICATION_RESPONSE_IS_INVALID = '915120'; + const TRANSACTION_THREE_D_SECURE_CAVV_ALGORITHM_IS_INVALID = '915122'; const TRANSACTION_THREE_D_SECURE_CAVV_IS_REQUIRED = '915116'; - const TRANSACTION_THREE_D_SECURE_XID_IS_REQUIRED = '915115'; + const TRANSACTION_THREE_D_SECURE_DIRECTORY_RESPONSE_IS_INVALID = '915121'; const TRANSACTION_THREE_D_SECURE_ECI_FLAG_IS_INVALID = '915114'; + const TRANSACTION_THREE_D_SECURE_ECI_FLAG_IS_REQUIRED = '915113'; const TRANSACTION_THREE_D_SECURE_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_CARD_TYPE = '915131'; + const TRANSACTION_THREE_D_SECURE_THREE_D_SECURE_VERSION_IS_INVALID = '915119'; + const TRANSACTION_THREE_D_SECURE_TOKEN_IS_INVALID = '91568'; + const TRANSACTION_THREE_D_SECURE_TRANSACTION_DATA_DOESNT_MATCH_VERIFY = '91570'; + const TRANSACTION_THREE_D_SECURE_XID_IS_REQUIRED = '915115'; const TRANSACTION_TYPE_IS_INVALID = '91523'; const TRANSACTION_TYPE_IS_REQUIRED = '91524'; const TRANSACTION_UNSUPPORTED_VOICE_AUTHORIZATION = '91539'; @@ -625,5 +671,6 @@ class Codes const VERIFICATION_OPTIONS_MERCHANT_ACCOUNT_IS_SUSPENDED = '94205'; const VERIFICATION_OPTIONS_MERCHANT_ACCOUNT_IS_FORBIDDEN = '94206'; const VERIFICATION_OPTIONS_MERCHANT_ACCOUNT_CANNOT_BE_SUB_MERCHANT_ACCOUNT = '94208'; + const VERIFICATION_OPTIONS_ACCOUNT_TYPE_IS_INVALID = '942184'; + const VERIFICATION_OPTIONS_ACCOUNT_TYPE_NOT_SUPPORTED = '942185'; } -class_alias('Braintree\Error\Codes', 'Braintree_Error_Codes'); diff --git a/lib/Braintree/Error/ErrorCollection.php b/lib/Braintree/Error/ErrorCollection.php index 79690e0..8c4db63 100644 --- a/lib/Braintree/Error/ErrorCollection.php +++ b/lib/Braintree/Error/ErrorCollection.php @@ -2,6 +2,8 @@ namespace Braintree\Error; use Braintree\Util; +use Countable; +use JsonSerializable; /** * @@ -16,7 +18,7 @@ * * @property-read object $errors */ -class ErrorCollection implements \Countable +class ErrorCollection implements Countable, JsonSerializable { private $_errors; @@ -119,5 +121,15 @@ public function __toString() { return sprintf('%s', $this->_errors); } + + /** + * Implementation of JsonSerializable + * + * @ignore + * @return array + */ + public function jsonSerialize() + { + return $this->_errors->deepAll(); + } } -class_alias('Braintree\Error\ErrorCollection', 'Braintree_Error_ErrorCollection'); diff --git a/lib/Braintree/Error/Validation.php b/lib/Braintree/Error/Validation.php index 79a4cc1..965bbb5 100644 --- a/lib/Braintree/Error/Validation.php +++ b/lib/Braintree/Error/Validation.php @@ -57,4 +57,3 @@ public function __get($name) return isset($this->$varName) ? $this->$varName : null; } } -class_alias('Braintree\Error\Validation', 'Braintree_Error_Validation'); diff --git a/lib/Braintree/Error/ValidationErrorCollection.php b/lib/Braintree/Error/ValidationErrorCollection.php index ff3683e..1c433f8 100644 --- a/lib/Braintree/Error/ValidationErrorCollection.php +++ b/lib/Braintree/Error/ValidationErrorCollection.php @@ -102,7 +102,6 @@ public function __toString() { $output = []; - // TODO: implement scope if (!empty($this->_errors)) { $output[] = $this->_inspect($this->_errors); } @@ -120,12 +119,14 @@ public function __toString() private function _inspect($errors, $scope = null) { $eOutput = '[' . __CLASS__ . '/errors:['; + $outputErrs = []; foreach($errors AS $error => $errorObj) { - $outputErrs[] = "({$errorObj->error['code']} {$errorObj->error['message']})"; + if (is_array($errorObj->error)) { + $outputErrs[] = "({$errorObj->error['code']} {$errorObj->error['message']})"; + } } $eOutput .= join(', ', $outputErrs) . ']]'; return $eOutput; } } -class_alias('Braintree\Error\ValidationErrorCollection', 'Braintree_Error_ValidationErrorCollection'); diff --git a/lib/Braintree/EuropeBankAccount.php b/lib/Braintree/EuropeBankAccount.php deleted file mode 100644 index b661e70..0000000 --- a/lib/Braintree/EuropeBankAccount.php +++ /dev/null @@ -1,67 +0,0 @@ -== More information == - * - * See {@link https://developers.braintreepayments.com/javascript+php}
- * - * @package Braintree - * @category Resources - * - * @property-read string $account-holder-name - * @property-read string $bic - * @property-read string $customerId - * @property-read string $default - * @property-read string $image-url - * @property-read string $mandate-reference-number - * @property-read string $masked-iban - * @property-read string $token - */ -class EuropeBankAccount extends Base -{ - - /* instance methods */ - /** - * returns false if default is null or false - * - * @return boolean - */ - public function isDefault() - { - return $this->default; - } - - /** - * factory method: returns an instance of EuropeBankAccount - * to the requesting method, with populated properties - * - * @ignore - * @return EuropeBankAccount - */ - public static function factory($attributes) - { - $defaultAttributes = [ - ]; - - $instance = new self(); - $instance->_initialize(array_merge($defaultAttributes, $attributes)); - return $instance; - } - - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $europeBankAccountAttribs array of EuropeBankAccount properties - * @return void - */ - protected function _initialize($europeBankAccountAttribs) - { - $this->_attributes = $europeBankAccountAttribs; - } -} -class_alias('Braintree\EuropeBankAccount', 'Braintree_EuropeBankAccount'); diff --git a/lib/Braintree/Exception.php b/lib/Braintree/Exception.php index 58d0805..094117b 100644 --- a/lib/Braintree/Exception.php +++ b/lib/Braintree/Exception.php @@ -10,4 +10,3 @@ class Exception extends \Exception { } -class_alias('Braintree\Exception', 'Braintree_Exception'); diff --git a/lib/Braintree/Exception/Authentication.php b/lib/Braintree/Exception/Authentication.php index 1f87746..53c2234 100644 --- a/lib/Braintree/Exception/Authentication.php +++ b/lib/Braintree/Exception/Authentication.php @@ -14,4 +14,3 @@ class Authentication extends Exception { } -class_alias('Braintree\Exception\Authentication', 'Braintree_Exception_Authentication'); diff --git a/lib/Braintree/Exception/Authorization.php b/lib/Braintree/Exception/Authorization.php index d6d9b2a..dd669e3 100644 --- a/lib/Braintree/Exception/Authorization.php +++ b/lib/Braintree/Exception/Authorization.php @@ -16,4 +16,3 @@ class Authorization extends Exception { } -class_alias('Braintree\Exception\Authorization', 'Braintree_Exception_Authorization'); diff --git a/lib/Braintree/Exception/Configuration.php b/lib/Braintree/Exception/Configuration.php index d54caee..1a9280a 100644 --- a/lib/Braintree/Exception/Configuration.php +++ b/lib/Braintree/Exception/Configuration.php @@ -12,6 +12,4 @@ */ class Configuration extends Exception { - } -class_alias('Braintree\Exception\Configuration', 'Braintree_Exception_Configuration'); diff --git a/lib/Braintree/Exception/Connection.php b/lib/Braintree/Exception/Connection.php index 474cdbb..2a766f2 100644 --- a/lib/Braintree/Exception/Connection.php +++ b/lib/Braintree/Exception/Connection.php @@ -14,4 +14,3 @@ class Connection extends Exception { } -class_alias('Braintree\Exception\Connection', 'Braintree_Exception_Connection'); \ No newline at end of file diff --git a/lib/Braintree/Exception/DownForMaintenance.php b/lib/Braintree/Exception/DownForMaintenance.php deleted file mode 100644 index ab5d5a1..0000000 --- a/lib/Braintree/Exception/DownForMaintenance.php +++ /dev/null @@ -1,16 +0,0 @@ -_attributes) .']'; } - } -class_alias('Braintree\FacilitatedDetails', 'Braintree_FacilitatedDetails'); diff --git a/lib/Braintree/FacilitatorDetails.php b/lib/Braintree/FacilitatorDetails.php index eda4fcc..3783f02 100644 --- a/lib/Braintree/FacilitatorDetails.php +++ b/lib/Braintree/FacilitatorDetails.php @@ -1,6 +1,11 @@ _attributes) .']'; } - } -class_alias('Braintree\FacilitatorDetails', 'Braintree_FacilitatorDetails'); diff --git a/lib/Braintree/Gateway.php b/lib/Braintree/Gateway.php index 701a599..990c621 100644 --- a/lib/Braintree/Gateway.php +++ b/lib/Braintree/Gateway.php @@ -15,12 +15,19 @@ class Gateway */ public $config; + /** + * + * @var GraphQLClient + */ + public $graphQLClient; + public function __construct($config) { if (is_array($config)) { $config = new Configuration($config); } $this->config = $config; + $this->graphQLClient = new GraphQLClient($config); } /** @@ -221,15 +228,6 @@ public function transactionLineItem() return new TransactionLineItemGateway($this); } - /** - * - * @return TransparentRedirectGateway - */ - public function transparentRedirect() - { - return new TransparentRedirectGateway($this); - } - /** * * @return UsBankAccountGateway @@ -248,15 +246,6 @@ public function usBankAccountVerification() return new UsBankAccountVerificationGateway($this); } - /** - * - * @return IdealPaymentGateway - */ - public function idealPayment() - { - return new IdealPaymentGateway($this); - } - /** * * @return WebhookNotificationGateway @@ -275,4 +264,3 @@ public function webhookTesting() return new WebhookTestingGateway($this); } } -class_alias('Braintree\Gateway', 'Braintree_Gateway'); diff --git a/lib/Braintree/GrantedPaymentInstrumentUpdate.php b/lib/Braintree/GrantedPaymentInstrumentUpdate.php index 551b0c8..899de24 100644 --- a/lib/Braintree/GrantedPaymentInstrumentUpdate.php +++ b/lib/Braintree/GrantedPaymentInstrumentUpdate.php @@ -70,4 +70,3 @@ public function __toString() Util::attributesToString($this->_attributes) . ']'; } } -class_alias('Braintree\GrantedPaymentInstrumentUpdate', 'Braintree_GrantedPaymentInstrumentUpdate'); diff --git a/lib/Braintree/GraphQL.php b/lib/Braintree/GraphQL.php index 488d6fe..4ced784 100644 --- a/lib/Braintree/GraphQL.php +++ b/lib/Braintree/GraphQL.php @@ -4,7 +4,7 @@ use finfo; /** - * Braintree GraphQL Client + * Braintree GraphQL service * process GraphQL requests using curl */ class GraphQL extends Http @@ -25,7 +25,7 @@ public function graphQLHeaders() ]; } - public function request($definition, $variables) + public function request($definition, $variables = Null) { $graphQLRequest = ["query" => $definition]; if ($variables) { @@ -40,5 +40,3 @@ public function request($definition, $variables) return $result; } } - -class_alias('Braintree\GraphQL', 'Braintree_GraphQL'); diff --git a/lib/Braintree/GraphQLClient.php b/lib/Braintree/GraphQLClient.php new file mode 100644 index 0000000..910c7b6 --- /dev/null +++ b/lib/Braintree/GraphQLClient.php @@ -0,0 +1,19 @@ +_service = new GraphQL($config); + } + + public function query($definition, $variables = Null) + { + return $this->_service->request($definition, $variables); + } +} diff --git a/lib/Braintree/Http.php b/lib/Braintree/Http.php index 616be51..a07b3b7 100644 --- a/lib/Braintree/Http.php +++ b/lib/Braintree/Http.php @@ -191,11 +191,11 @@ public function _doUrlRequest($httpVerb, $url, $requestBody = null, $file = null } curl_close($curl); - if ($this->_config->sslOn()) { - if ($httpStatus == 0) { - throw new Exception\SSLCertificate($error, $error_code); - } - } else if ($error_code) { + if ($this->_config->sslOn() && $error_code == 35) { + throw new Exception\SSLCertificate($error, $error_code); + } + + if ($error_code) { throw new Exception\Connection($error, $error_code); } @@ -270,4 +270,3 @@ private function getCaFile() return $memo; } } -class_alias('Braintree\Http', 'Braintree_Http'); diff --git a/lib/Braintree/IbanBankAccount.php b/lib/Braintree/IbanBankAccount.php deleted file mode 100644 index 8e53563..0000000 --- a/lib/Braintree/IbanBankAccount.php +++ /dev/null @@ -1,57 +0,0 @@ -_attributes) . ']'; - } - - /** - * sets instance properties from an array of values - * - * @ignore - * @access protected - * @param array $ibanAttribs array of ibanBankAccount data - * @return void - */ - protected function _initialize($ibanAttribs) - { - // set the attributes - $this->_attributes = $ibanAttribs; - } - - /** - * factory method: returns an instance of IbanBankAccount - * to the requesting method, with populated properties - * @ignore - * @return IbanBankAccount - */ - public static function factory($attributes) - { - $instance = new self(); - $instance->_initialize($attributes); - return $instance; - } -} -class_alias('Braintree\IbanBankAccount', 'Braintree_IbanBankAccount'); diff --git a/lib/Braintree/IdealPayment.php b/lib/Braintree/IdealPayment.php deleted file mode 100644 index 2ada135..0000000 --- a/lib/Braintree/IdealPayment.php +++ /dev/null @@ -1,92 +0,0 @@ -== More information == - * - * - * @package Braintree - * @category Resources - * - * @property-read string $id - * @property-read string $idealTransactionId - * @property-read string $currency - * @property-read string $amount - * @property-read string $status - * @property-read string $orderId - * @property-read string $issuer - * @property-read string $ibanBankAccount - */ -class IdealPayment extends Base -{ - /** - * factory method: returns an instance of IdealPayment - * to the requesting method, with populated properties - * - * @ignore - * @return IdealPayment - */ - public static function factory($attributes) - { - $instance = new self(); - $instance->_initialize($attributes); - return $instance; - } - - /* instance methods */ - - /** - * sets instance properties from an array of values - * - * @access protected - * @param array $idealPaymentAttribs array of idealPayment data - * @return void - */ - protected function _initialize($idealPaymentAttribs) - { - // set the attributes - $this->_attributes = $idealPaymentAttribs; - - $ibanBankAccount = isset($idealPaymentAttribs['ibanBankAccount']) ? - IbanBankAccount::factory($idealPaymentAttribs['ibanBankAccount']) : - null; - $this->_set('ibanBankAccount', $ibanBankAccount); - } - - /** - * create a printable representation of the object as: - * ClassName[property=value, property=value] - * @return string - */ - public function __toString() - { - return __CLASS__ . '[' . - Util::attributesToString($this->_attributes) . ']'; - } - - - // static methods redirecting to gateway - - public static function find($idealPaymentId) - { - return Configuration::gateway()->idealPayment()->find($idealPaymentId); - } - - public static function sale($idealPaymentId, $transactionAttribs) - { - $transactionAttribs['options'] = [ - 'submitForSettlement' => true - ]; - return Configuration::gateway()->idealPayment()->sale($idealPaymentId, $transactionAttribs); - } -} -class_alias('Braintree\IdealPayment', 'Braintree_IdealPayment'); diff --git a/lib/Braintree/IdealPaymentGateway.php b/lib/Braintree/IdealPaymentGateway.php deleted file mode 100644 index 258bc46..0000000 --- a/lib/Braintree/IdealPaymentGateway.php +++ /dev/null @@ -1,104 +0,0 @@ -== More information == - * - * - * @package Braintree - * @category Resources - */ -class IdealPaymentGateway -{ - private $_gateway; - private $_config; - private $_http; - - public function __construct($gateway) - { - $this->_gateway = $gateway; - $this->_config = $gateway->config; - $this->_config->assertHasAccessTokenOrKeys(); - $this->_http = new Http($gateway->config); - } - - /** - * find an IdealPayment by id - * - * @access public - * @param string $idealPaymentId - * @return IdealPayment - * @throws Exception\NotFound - */ - public function find($idealPaymentId) - { - try { - $path = $this->_config->merchantPath() . '/ideal_payments/' . $idealPaymentId; - $response = $this->_http->get($path); - return IdealPayment::factory($response['idealPayment']); - } catch (Exception\NotFound $e) { - throw new Exception\NotFound( - 'iDEAL Payment with id ' . $idealPaymentId . ' not found' - ); - } - } - - /** - * create a new sale for the current IdealPayment - * - * @param string $idealPaymentId - * @param array $transactionAttribs - * @return Result\Successful|Result\Error - * @see Transaction::sale() - */ - public function sale($idealPaymentId, $transactionAttribs) - { - return Transaction::sale( - array_merge( - $transactionAttribs, - ['paymentMethodNonce' => $idealPaymentId] - ) - ); - } - - /** - * generic method for validating incoming gateway responses - * - * creates a new IdealPayment object and encapsulates - * it inside a Result\Successful object, or - * encapsulates a Errors object inside a Result\Error - * alternatively, throws an Unexpected exception if the response is invalid. - * - * @ignore - * @param array $response gateway response values - * @return Result\Successful|Result\Error - * @throws Exception\Unexpected - */ - private function _verifyGatewayResponse($response) - { - if (isset($response['idealPayment'])) { - // return a populated instance of IdealPayment - return new Result\Successful( - IdealPayment::factory($response['idealPayment']) - ); - } else if (isset($response['apiErrorResponse'])) { - return new Result\Error($response['apiErrorResponse']); - } else { - throw new Exception\Unexpected( - 'Expected Ideal Payment or apiErrorResponse' - ); - } - } -} -class_alias('Braintree\IdealPaymentGateway', 'Braintree_IdealPaymentGateway'); diff --git a/lib/Braintree/Instance.php b/lib/Braintree/Instance.php index ba0d272..0011f1b 100644 --- a/lib/Braintree/Instance.php +++ b/lib/Braintree/Instance.php @@ -71,4 +71,3 @@ private function _initializeFromArray($attributes) } } -class_alias('Braintree\Instance', 'Braintree_Instance'); diff --git a/lib/Braintree/IsNode.php b/lib/Braintree/IsNode.php index 6db01b0..05583cc 100644 --- a/lib/Braintree/IsNode.php +++ b/lib/Braintree/IsNode.php @@ -21,4 +21,3 @@ public function toParam() return $this->searchTerms; } } -class_alias('Braintree\IsNode', 'Braintree_IsNode'); diff --git a/lib/Braintree/KeyValueNode.php b/lib/Braintree/KeyValueNode.php index 1fd0139..db7c553 100644 --- a/lib/Braintree/KeyValueNode.php +++ b/lib/Braintree/KeyValueNode.php @@ -20,4 +20,3 @@ public function toParam() return $this->searchTerm; } } -class_alias('Braintree\KeyValueNode', 'Braintree_KeyValueNode'); diff --git a/lib/Braintree/LocalPaymentCompleted.php b/lib/Braintree/LocalPaymentCompleted.php index 07b7360..8fd3023 100644 --- a/lib/Braintree/LocalPaymentCompleted.php +++ b/lib/Braintree/LocalPaymentCompleted.php @@ -17,11 +17,10 @@ * @package Braintree * @category Resources * - * @property-read string $grantOwnerMerchantId - * @property-read string $grantRecipientMerchantId + * @property-read string $paymentId + * @property-read string $payerId * @property-read string $paymentMethodNonce - * @property-read string $token - * @property-read string $updatedFields + * @property-read \Braintree\Transaction $transaction */ class LocalPaymentCompleted extends Base { @@ -52,6 +51,14 @@ protected function _initialize($localPaymentCompletedAttribs) { // set the attributes $this->_attributes = $localPaymentCompletedAttribs; + + if (isset($transactionAttribs['transaction'])) { + $this->_set('transaction', + new Transaction( + $transactionAttribs['transaction'] + ) + ); + } } /** @@ -65,4 +72,3 @@ public function __toString() Util::attributesToString($this->_attributes) . ']'; } } -class_alias('Braintree\LocalPaymentCompleted', 'Braintree_LocalPaymentCompleted'); diff --git a/lib/Braintree/MasterpassCard.php b/lib/Braintree/MasterpassCard.php index aa78c8b..af6d480 100644 --- a/lib/Braintree/MasterpassCard.php +++ b/lib/Braintree/MasterpassCard.php @@ -12,22 +12,22 @@ * @package Braintree * @category Resources * - * @property-read string $billingAddress + * @property-read \Braintree\Address $billingAddress * @property-read string $bin * @property-read string $cardType * @property-read string $cardholderName * @property-read string $commercial * @property-read string $countryOfIssuance - * @property-read string $createdAt + * @property-read \DateTime $createdAt * @property-read string $customerId * @property-read string $customerLocation * @property-read string $debit - * @property-read string $default + * @property-read boolean $default * @property-read string $durbinRegulated * @property-read string $expirationDate * @property-read string $expirationMonth * @property-read string $expirationYear - * @property-read string $expired + * @property-read boolean $expired * @property-read string $healthcare * @property-read string $imageUrl * @property-read string $issuingBank @@ -36,10 +36,10 @@ * @property-read string $payroll * @property-read string $prepaid * @property-read string $productId - * @property-read string $subscriptions + * @property-read \Braintree\Subscription[] $subscriptions * @property-read string $token * @property-read string $uniqueNumberIdentifier - * @property-read string $updatedAt + * @property-read \DateTime $updatedAt */ class MasterpassCard extends Base { @@ -138,4 +138,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\MasterpassCard', 'Braintree_MasterpassCard'); diff --git a/lib/Braintree/Merchant.php b/lib/Braintree/Merchant.php index 09d8bf4..95ba6ec 100644 --- a/lib/Braintree/Merchant.php +++ b/lib/Braintree/Merchant.php @@ -33,4 +33,3 @@ public function __toString() Util::attributesToString($this->_attributes) .']'; } } -class_alias('Braintree\Merchant', 'Braintree_Merchant'); diff --git a/lib/Braintree/MerchantAccount.php b/lib/Braintree/MerchantAccount.php index 5bde533..0b9c2ee 100644 --- a/lib/Braintree/MerchantAccount.php +++ b/lib/Braintree/MerchantAccount.php @@ -1,6 +1,16 @@ merchantAccount()->update($merchant_account_id, $attributes); } } -class_alias('Braintree\MerchantAccount', 'Braintree_MerchantAccount'); diff --git a/lib/Braintree/MerchantAccount/AddressDetails.php b/lib/Braintree/MerchantAccount/AddressDetails.php index c4caf9a..9a3c2ca 100644 --- a/lib/Braintree/MerchantAccount/AddressDetails.php +++ b/lib/Braintree/MerchantAccount/AddressDetails.php @@ -7,4 +7,3 @@ class AddressDetails extends Instance { protected $_attributes = []; } -class_alias('Braintree\MerchantAccount\AddressDetails', 'Braintree_MerchantAccount_AddressDetails'); diff --git a/lib/Braintree/MerchantAccount/BusinessDetails.php b/lib/Braintree/MerchantAccount/BusinessDetails.php index 73a1622..99e95f5 100644 --- a/lib/Braintree/MerchantAccount/BusinessDetails.php +++ b/lib/Braintree/MerchantAccount/BusinessDetails.php @@ -20,4 +20,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\MerchantAccount\BusinessDetails', 'Braintree_MerchantAccount_BusinessDetails'); diff --git a/lib/Braintree/MerchantAccount/FundingDetails.php b/lib/Braintree/MerchantAccount/FundingDetails.php index 6fac0b5..167e943 100644 --- a/lib/Braintree/MerchantAccount/FundingDetails.php +++ b/lib/Braintree/MerchantAccount/FundingDetails.php @@ -7,4 +7,3 @@ class FundingDetails extends Instance { protected $_attributes = []; } -class_alias('Braintree\MerchantAccount\FundingDetails', 'Braintree_MerchantAccount_FundingDetails'); diff --git a/lib/Braintree/MerchantAccount/IndividualDetails.php b/lib/Braintree/MerchantAccount/IndividualDetails.php index a3eee90..8612d8c 100644 --- a/lib/Braintree/MerchantAccount/IndividualDetails.php +++ b/lib/Braintree/MerchantAccount/IndividualDetails.php @@ -20,4 +20,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\MerchantAccount\IndividualDetails', 'Braintree_MerchantAccount_IndividualDetails'); diff --git a/lib/Braintree/MerchantAccountGateway.php b/lib/Braintree/MerchantAccountGateway.php index a9704c8..663fd69 100644 --- a/lib/Braintree/MerchantAccountGateway.php +++ b/lib/Braintree/MerchantAccountGateway.php @@ -17,7 +17,7 @@ public function __construct($gateway) public function create($attribs) { - Util::verifyKeys(self::detectSignature($attribs), $attribs); + Util::verifyKeys(self::createSignature(), $attribs); return $this->_doCreate('/merchant_accounts/create_via_api', ['merchant_account' => $attribs]); } @@ -38,16 +38,6 @@ public function update($merchant_account_id, $attributes) return $this->_doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', ['merchant_account' => $attributes]); } - public static function detectSignature($attribs) - { - if (isset($attribs['applicantDetails'])) { - trigger_error("DEPRECATED: Passing applicantDetails to create is deprecated. Please use individual, business, and funding", E_USER_NOTICE); - return self::createDeprecatedSignature(); - } else { - return self::createSignature(); - } - } - public static function updateSignature() { $signature = self::createSignature(); @@ -119,31 +109,6 @@ public static function createSignature() ]; } - public static function createDeprecatedSignature() - { - $applicantDetailsAddressSignature = ['streetAddress', 'postalCode', 'locality', 'region']; - $applicantDetailsSignature = [ - 'companyName', - 'firstName', - 'lastName', - 'email', - 'phone', - 'dateOfBirth', - 'ssn', - 'taxId', - 'routingNumber', - 'accountNumber', - ['address' => $applicantDetailsAddressSignature] - ]; - - return [ - ['applicantDetails' => $applicantDetailsSignature], - 'id', - 'tosAccepted', - 'masterMerchantAccountId' - ]; - } - public function _doCreate($subPath, $params) { $fullPath = $this->_config->merchantPath() . $subPath; @@ -179,4 +144,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\MerchantAccountGateway', 'Braintree_MerchantAccountGateway'); diff --git a/lib/Braintree/MerchantGateway.php b/lib/Braintree/MerchantGateway.php index d628e88..a421af8 100644 --- a/lib/Braintree/MerchantGateway.php +++ b/lib/Braintree/MerchantGateway.php @@ -39,4 +39,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\MerchantGateway', 'Braintree_MerchantGateway'); diff --git a/lib/Braintree/Modification.php b/lib/Braintree/Modification.php index e1d32b2..1c44064 100644 --- a/lib/Braintree/Modification.php +++ b/lib/Braintree/Modification.php @@ -19,4 +19,3 @@ public function __toString() { return get_called_class() . '[' . Util::attributesToString($this->_attributes) . ']'; } } -class_alias('Braintree\Modification', 'Braintree_Modification'); diff --git a/lib/Braintree/MultipleValueNode.php b/lib/Braintree/MultipleValueNode.php index 397c610..7b9635f 100644 --- a/lib/Braintree/MultipleValueNode.php +++ b/lib/Braintree/MultipleValueNode.php @@ -38,4 +38,3 @@ public function toParam() return $this->items; } } -class_alias('Braintree\MultipleValueNode', 'Braintree_MultipleValueNode'); diff --git a/lib/Braintree/MultipleValueOrTextNode.php b/lib/Braintree/MultipleValueOrTextNode.php index c98ee95..6e10c45 100644 --- a/lib/Braintree/MultipleValueOrTextNode.php +++ b/lib/Braintree/MultipleValueOrTextNode.php @@ -44,4 +44,3 @@ public function toParam() return array_merge(parent::toParam(), $this->textNode->toParam()); } } -class_alias('Braintree\MultipleValueOrTextNode', 'Braintree_MultipleValueOrTextNode'); diff --git a/lib/Braintree/OAuthAccessRevocation.php b/lib/Braintree/OAuthAccessRevocation.php index 62a2897..93c6abb 100644 --- a/lib/Braintree/OAuthAccessRevocation.php +++ b/lib/Braintree/OAuthAccessRevocation.php @@ -4,8 +4,6 @@ /** * Braintree OAuth Revocation module * - * PHP Version 5 - * * @package Braintree */ class OAuthAccessRevocation extends Base @@ -29,4 +27,3 @@ protected function _initialize($attributes) $this->_attributes = $attributes; } } -class_alias('Braintree\OAuthAccessRevocation', 'Braintree_OAuthAccessRevocation'); diff --git a/lib/Braintree/OAuthCredentials.php b/lib/Braintree/OAuthCredentials.php index 60de5fb..6a322a2 100644 --- a/lib/Braintree/OAuthCredentials.php +++ b/lib/Braintree/OAuthCredentials.php @@ -31,4 +31,3 @@ public function __toString() Util::attributesToString($this->_attributes) .']'; } } -class_alias('Braintree\OAuthCredentials', 'Braintree_OAuthCredentials'); diff --git a/lib/Braintree/OAuthGateway.php b/lib/Braintree/OAuthGateway.php index 4e2d1b2..eaf4535 100644 --- a/lib/Braintree/OAuthGateway.php +++ b/lib/Braintree/OAuthGateway.php @@ -3,7 +3,6 @@ /** * Braintree OAuthGateway module - * PHP Version 5 * Creates and manages Braintree Addresses * * @package Braintree @@ -111,14 +110,4 @@ public function connectUrl($params = []) return $this->_config->baseUrl() . '/oauth/connect?' . $queryString; } - - /** - * @deprecated since version 3.26.1 - */ - public function computeSignature($url) - { - $key = hash('sha256', $this->_config->getClientSecret(), true); - return hash_hmac('sha256', $url, $key); - } } -class_alias('Braintree\OAuthGateway', 'Braintree_OAuthGateway'); diff --git a/lib/Braintree/OAuthResult.php b/lib/Braintree/OAuthResult.php index 9c3e4e6..cdb2ab5 100644 --- a/lib/Braintree/OAuthResult.php +++ b/lib/Braintree/OAuthResult.php @@ -31,4 +31,3 @@ public function __toString() Util::attributesToString($this->_attributes) .']'; } } -class_alias('Braintree\OAuthResult', 'Braintree_OAuthResult'); diff --git a/lib/Braintree/PaginatedCollection.php b/lib/Braintree/PaginatedCollection.php index 9deef04..8382a05 100644 --- a/lib/Braintree/PaginatedCollection.php +++ b/lib/Braintree/PaginatedCollection.php @@ -117,4 +117,3 @@ private function _getNextPage() $this->_items = $result->getCurrentPage(); } } -class_alias('Braintree\PaginatedCollection', 'Braintree_PaginatedCollection'); diff --git a/lib/Braintree/PaginatedResult.php b/lib/Braintree/PaginatedResult.php index 9b383ab..9edb046 100644 --- a/lib/Braintree/PaginatedResult.php +++ b/lib/Braintree/PaginatedResult.php @@ -29,4 +29,3 @@ public function getCurrentPage() return $this->_currentPage; } } -class_alias('Braintree\PaginatedResult', 'Braintree_PaginatedResult'); diff --git a/lib/Braintree/PartialMatchNode.php b/lib/Braintree/PartialMatchNode.php index 5d8dc91..057177b 100644 --- a/lib/Braintree/PartialMatchNode.php +++ b/lib/Braintree/PartialMatchNode.php @@ -15,4 +15,3 @@ public function endsWith($value) return $this; } } -class_alias('Braintree\PartialMatchNode', 'Braintree_PartialMatchNode'); diff --git a/lib/Braintree/PartnerMerchant.php b/lib/Braintree/PartnerMerchant.php index d5ac152..46922bd 100644 --- a/lib/Braintree/PartnerMerchant.php +++ b/lib/Braintree/PartnerMerchant.php @@ -38,4 +38,3 @@ protected function _initialize($attributes) $this->_attributes = $attributes; } } -class_alias('Braintree\PartnerMerchant', 'Braintree_PartnerMerchant'); diff --git a/lib/Braintree/PayPalAccount.php b/lib/Braintree/PayPalAccount.php index 15e334e..2764dd8 100644 --- a/lib/Braintree/PayPalAccount.php +++ b/lib/Braintree/PayPalAccount.php @@ -17,10 +17,17 @@ * @package Braintree * @category Resources * + * @property-read string $billingAgreementId + * @property-read \DateTime $createdAt * @property-read string $customerId + * @property-read boolean $default * @property-read string $email - * @property-read string $token * @property-read string $imageUrl + * @property-read string $payerId + * @property-read \DateTime $revokedAt + * @property-read \Braintree\Subscription[] $subscriptions + * @property-read string $token + * @property-read \DateTime $updatedAt */ class PayPalAccount extends Base { @@ -106,4 +113,3 @@ public static function sale($token, $transactionAttribs) return Configuration::gateway()->payPalAccount()->sale($token, $transactionAttribs); } } -class_alias('Braintree\PayPalAccount', 'Braintree_PayPalAccount'); diff --git a/lib/Braintree/PayPalAccountGateway.php b/lib/Braintree/PayPalAccountGateway.php index 9302a17..3d7b2f7 100644 --- a/lib/Braintree/PayPalAccountGateway.php +++ b/lib/Braintree/PayPalAccountGateway.php @@ -175,4 +175,3 @@ private function _validateId($identifier = null, $identifierType = 'token') } } } -class_alias('Braintree\PayPalAccountGateway', 'Braintree_PayPalAccountGateway'); diff --git a/lib/Braintree/PaymentInstrumentType.php b/lib/Braintree/PaymentInstrumentType.php index 8218e42..6668e10 100644 --- a/lib/Braintree/PaymentInstrumentType.php +++ b/lib/Braintree/PaymentInstrumentType.php @@ -3,17 +3,15 @@ class PaymentInstrumentType { - const PAYPAL_ACCOUNT = 'paypal_account'; - const COINBASE_ACCOUNT = 'coinbase_account'; - const EUROPE_BANK_ACCOUNT = 'europe_bank_account'; + const ANDROID_PAY_CARD = 'android_pay_card'; + const APPLE_PAY_CARD = 'apple_pay_card'; const CREDIT_CARD = 'credit_card'; - const VISA_CHECKOUT_CARD = 'visa_checkout_card'; + const LOCAL_PAYMENT = 'local_payment'; const MASTERPASS_CARD = 'masterpass_card'; - const APPLE_PAY_CARD = 'apple_pay_card'; - const ANDROID_PAY_CARD = 'android_pay_card'; - const VENMO_ACCOUNT = 'venmo_account'; - const US_BANK_ACCOUNT = 'us_bank_account'; - const IDEAL_PAYMENT = 'ideal_payment'; + const PAYPAL_ACCOUNT = 'paypal_account'; + const PAYPAL_HERE = 'paypal_here'; const SAMSUNG_PAY_CARD = 'samsung_pay_card'; + const US_BANK_ACCOUNT = 'us_bank_account'; + const VENMO_ACCOUNT = 'venmo_account'; + const VISA_CHECKOUT_CARD = 'visa_checkout_card'; } -class_alias('Braintree\PaymentInstrumentType', 'Braintree_PaymentInstrumentType'); diff --git a/lib/Braintree/PaymentMethod.php b/lib/Braintree/PaymentMethod.php index f620a38..f524b8f 100644 --- a/lib/Braintree/PaymentMethod.php +++ b/lib/Braintree/PaymentMethod.php @@ -41,4 +41,3 @@ public static function delete($token, $options=[]) return Configuration::gateway()->paymentMethod()->delete($token, $options); } } -class_alias('Braintree\PaymentMethod', 'Braintree_PaymentMethod'); diff --git a/lib/Braintree/PaymentMethodGateway.php b/lib/Braintree/PaymentMethodGateway.php index 66630f5..bca7b8d 100644 --- a/lib/Braintree/PaymentMethodGateway.php +++ b/lib/Braintree/PaymentMethodGateway.php @@ -53,33 +53,7 @@ public function find($token) try { $path = $this->_config->merchantPath() . '/payment_methods/any/' . $token; $response = $this->_http->get($path); - if (isset($response['creditCard'])) { - return CreditCard::factory($response['creditCard']); - } else if (isset($response['paypalAccount'])) { - return PayPalAccount::factory($response['paypalAccount']); - } else if (isset($response['coinbaseAccount'])) { - return CoinbaseAccount::factory($response['coinbaseAccount']); - } else if (isset($response['applePayCard'])) { - return ApplePayCard::factory($response['applePayCard']); - } else if (isset($response['androidPayCard'])) { - return AndroidPayCard::factory($response['androidPayCard']); - } else if (isset($response['amexExpressCheckoutCard'])) { - return AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']); - } else if (isset($response['europeBankAccount'])) { - return EuropeBankAccount::factory($response['europeBankAccount']); - } else if (isset($response['usBankAccount'])) { - return UsBankAccount::factory($response['usBankAccount']); - } else if (isset($response['venmoAccount'])) { - return VenmoAccount::factory($response['venmoAccount']); - } else if (isset($response['visaCheckoutCard'])) { - return VisaCheckoutCard::factory($response['visaCheckoutCard']); - } else if (isset($response['masterpassCard'])) { - return MasterpassCard::factory($response['masterpassCard']); - } else if (isset($response['samsungPayCard'])) { - return SamsungPayCard::factory($response['samsungPayCard']); - } else if (is_array($response)) { - return UnknownPaymentMethod::factory($response); - } + return PaymentMethodParser::parsePaymentMethod($response); } catch (Exception\NotFound $e) { throw new Exception\NotFound( 'payment method with token ' . $token . ' not found' @@ -111,7 +85,7 @@ public function grant($sharedPaymentMethodToken, $attribs=[]) } $options = [ 'shared_payment_method_token' => $sharedPaymentMethodToken ]; - return $this->_doCreate( + return $this->_doGrant( '/payment_methods/grant', [ 'payment_method' => array_merge($attribs, $options) @@ -121,7 +95,7 @@ public function grant($sharedPaymentMethodToken, $attribs=[]) public function revoke($sharedPaymentMethodToken) { - return $this->_doCreate( + return $this->_doRevoke( '/payment_methods/revoke', [ 'payment_method' => [ @@ -139,6 +113,7 @@ private static function baseSignature() 'makeDefault', 'verificationMerchantAccountId', 'verifyCard', + 'verificationAccountType', 'verificationAmount', 'usBankAccountVerificationMethod', ['paypal' => [ @@ -177,7 +152,10 @@ private static function baseSignature() public static function createSignature() { - $signature = array_merge(self::baseSignature(), ['customerId', 'paypalRefreshToken', 'paypalVaultWithoutUpgrade']); + $signature = array_merge(self::baseSignature(), [ + 'customerId', + 'paypalRefreshToken', + ]); return $signature; } @@ -189,11 +167,22 @@ public static function updateSignature() 'updateExisting' ] ]); + $threeDSPassThruSignature = [ + 'authenticationResponse', + 'cavv', + 'cavvAlgorithm', + 'directoryResponse', + 'dsTransactionId', + 'eciFlag', + 'threeDSecureVersion', + 'xid' + ]; $signature = array_merge(self::baseSignature(), [ 'deviceSessionId', 'venmoSdkPaymentMethodCode', 'fraudMerchantId', - ['billingAddress' => $billingAddressSignature] + ['billingAddress' => $billingAddressSignature], + ['threeDSecurePassThru' => $threeDSPassThruSignature] ]); return $signature; } @@ -219,6 +208,22 @@ public function _doCreate($subPath, $params) return $this->_verifyGatewayResponse($response); } + public function _doGrant($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyGrantResponse($response); + } + + public function _doRevoke($subPath, $params) + { + $fullPath = $this->_config->merchantPath() . $subPath; + $response = $this->_http->post($fullPath, $params); + + return $this->_verifyRevokeResponse($response); + } + /** * sends the update request to the gateway * @@ -265,76 +270,43 @@ public function _doDelete($subPath) */ private function _verifyGatewayResponse($response) { - if (isset($response['creditCard'])) { + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else if (($response)) { return new Result\Successful( - CreditCard::factory($response['creditCard']), + PaymentMethodParser::parsePaymentMethod($response), 'paymentMethod' ); - } else if (isset($response['paypalAccount'])) { - return new Result\Successful( - PayPalAccount::factory($response['paypalAccount']), - "paymentMethod" - ); - } else if (isset($response['coinbaseAccount'])) { - return new Result\Successful( - CoinbaseAccount::factory($response['coinbaseAccount']), - "paymentMethod" - ); - } else if (isset($response['applePayCard'])) { - return new Result\Successful( - ApplePayCard::factory($response['applePayCard']), - "paymentMethod" - ); - } else if (isset($response['androidPayCard'])) { - return new Result\Successful( - AndroidPayCard::factory($response['androidPayCard']), - "paymentMethod" - ); - } else if (isset($response['amexExpressCheckoutCard'])) { - return new Result\Successful( - AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']), - "paymentMethod" - ); - } else if (isset($response['usBankAccount'])) { - return new Result\Successful( - UsBankAccount::factory($response['usBankAccount']), - "paymentMethod" - ); - } else if (isset($response['venmoAccount'])) { - return new Result\Successful( - VenmoAccount::factory($response['venmoAccount']), - "paymentMethod" - ); - } else if (isset($response['visaCheckoutCard'])) { - return new Result\Successful( - VisaCheckoutCard::factory($response['visaCheckoutCard']), - "paymentMethod" - ); - } else if (isset($response['masterpassCard'])) { - return new Result\Successful( - MasterpassCard::factory($response['masterpassCard']), - "paymentMethod" - ); - } else if (isset($response['samsungPayCard'])) { - return new Result\Successful( - MasterpassCard::factory($response['samsungPayCard']), - "paymentMethod" + } else { + throw new Exception\Unexpected( + 'Expected payment method or apiErrorResponse' ); + } + } + + private function _verifyGrantResponse($response) { + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); } else if (isset($response['paymentMethodNonce'])) { return new Result\Successful( PaymentMethodNonce::factory($response['paymentMethodNonce']), - "paymentMethodNonce" + 'paymentMethodNonce' ); - } else if (isset($response['apiErrorResponse'])) { - return new Result\Error($response['apiErrorResponse']); - } else if (is_array($response)) { - return new Result\Successful( - UnknownPaymentMethod::factory($response), - "paymentMethod" + } else { + throw new Exception\Unexpected( + 'Expected paymentMethodNonce or apiErrorResponse' ); + } + } + + private function _verifyRevokeResponse($response) { + if (isset($response['apiErrorResponse'])) { + return new Result\Error($response['apiErrorResponse']); + } else if (isset($response['success'])) { + return new Result\Successful(); } else { throw new Exception\Unexpected( - 'Expected payment method or apiErrorResponse' + 'Expected success or apiErrorResponse' ); } } @@ -360,4 +332,3 @@ private function _validateId($identifier = null, $identifierType = 'token') } } } -class_alias('Braintree\PaymentMethodGateway', 'Braintree_PaymentMethodGateway'); diff --git a/lib/Braintree/PaymentMethodNonce.php b/lib/Braintree/PaymentMethodNonce.php index e125e21..832243e 100644 --- a/lib/Braintree/PaymentMethodNonce.php +++ b/lib/Braintree/PaymentMethodNonce.php @@ -16,14 +16,20 @@ * * @package Braintree * @category Resources + * + * @property-read \Braintree\BinData $binData + * @property-read boolean $default + * @property-read string $nonce + * @property-read \Braintree\ThreeDSecureInfo $threeDSecureInfo + * @property-read string $type */ class PaymentMethodNonce extends Base { // static methods redirecting to gateway - public static function create($token) + public static function create($token, $params = []) { - return Configuration::gateway()->paymentMethodNonce()->create($token); + return Configuration::gateway()->paymentMethodNonce()->create($token, $params); } public static function find($nonce) @@ -44,13 +50,16 @@ protected function _initialize($nonceAttributes) $this->_set('nonce', $nonceAttributes['nonce']); $this->_set('type', $nonceAttributes['type']); - if(isset($nonceAttributes['threeDSecureInfo'])) { - $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($nonceAttributes['threeDSecureInfo'])); + if(isset($nonceAttributes['authenticationInsight'])) { + $this->_set('authenticationInsight', $nonceAttributes['authenticationInsight']); } if(isset($nonceAttributes['binData'])) { $this->_set('binData', BinData::factory($nonceAttributes['binData'])); } + + if(isset($nonceAttributes['threeDSecureInfo'])) { + $this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($nonceAttributes['threeDSecureInfo'])); + } } } -class_alias('Braintree\PaymentMethodNonce', 'Braintree_PaymentMethodNonce'); diff --git a/lib/Braintree/PaymentMethodNonceGateway.php b/lib/Braintree/PaymentMethodNonceGateway.php index 40ad8af..3023b7c 100644 --- a/lib/Braintree/PaymentMethodNonceGateway.php +++ b/lib/Braintree/PaymentMethodNonceGateway.php @@ -31,11 +31,19 @@ public function __construct($gateway) } - public function create($token) + public function create($token, $params = []) { $subPath = '/payment_methods/' . $token . '/nonces'; $fullPath = $this->_config->merchantPath() . $subPath; - $response = $this->_http->post($fullPath); + $schema = [[ + 'paymentMethodNonce' => [ + 'merchantAccountId', + 'authenticationInsight', + 'amount' + ] + ]]; + Util::verifyKeys($schema, $params); + $response = $this->_http->post($fullPath, $params); return new Result\Successful( PaymentMethodNonce::factory($response['paymentMethodNonce']), @@ -61,4 +69,3 @@ public function find($nonce) } } -class_alias('Braintree\PaymentMethodNonceGateway', 'Braintree_PaymentMethodNonceGateway'); diff --git a/lib/Braintree/PaymentMethodParser.php b/lib/Braintree/PaymentMethodParser.php new file mode 100644 index 0000000..7175a67 --- /dev/null +++ b/lib/Braintree/PaymentMethodParser.php @@ -0,0 +1,53 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + */ +class PaymentMethodParser +{ + public static function parsePaymentMethod($response) + { + if (isset($response['creditCard'])) { + return CreditCard::factory($response['creditCard']); + } else if (isset($response['paypalAccount'])) { + return PayPalAccount::factory($response['paypalAccount']); + } else if (isset($response['applePayCard'])) { + return ApplePayCard::factory($response['applePayCard']); + } else if (isset($response['androidPayCard'])) { + return AndroidPayCard::factory($response['androidPayCard']); + } else if (isset($response['amexExpressCheckoutCard'])) { + return AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']); + } else if (isset($response['usBankAccount'])) { + return UsBankAccount::factory($response['usBankAccount']); + } else if (isset($response['venmoAccount'])) { + return VenmoAccount::factory($response['venmoAccount']); + } else if (isset($response['visaCheckoutCard'])) { + return VisaCheckoutCard::factory($response['visaCheckoutCard']); + } else if (isset($response['masterpassCard'])) { + return MasterpassCard::factory($response['masterpassCard']); + } else if (isset($response['samsungPayCard'])) { + return SamsungPayCard::factory($response['samsungPayCard']); + } else if (is_array($response)) { + return UnknownPaymentMethod::factory($response); + } else { + throw new Exception\Unexpected( + 'Expected payment method' + ); + } + } +} diff --git a/lib/Braintree/Plan.php b/lib/Braintree/Plan.php index a92c604..79870ea 100644 --- a/lib/Braintree/Plan.php +++ b/lib/Braintree/Plan.php @@ -1,6 +1,23 @@ plan()->all(); } } -class_alias('Braintree\Plan', 'Braintree_Plan'); diff --git a/lib/Braintree/PlanGateway.php b/lib/Braintree/PlanGateway.php index 22beaee..01d1a8a 100644 --- a/lib/Braintree/PlanGateway.php +++ b/lib/Braintree/PlanGateway.php @@ -31,4 +31,3 @@ public function all() ); } } -class_alias('Braintree\PlanGateway', 'Braintree_PlanGateway'); diff --git a/lib/Braintree/ProcessorResponseTypes.php b/lib/Braintree/ProcessorResponseTypes.php new file mode 100644 index 0000000..5bcfacc --- /dev/null +++ b/lib/Braintree/ProcessorResponseTypes.php @@ -0,0 +1,14 @@ +searchTerms; } } -class_alias('Braintree\RangeNode', 'Braintree_RangeNode'); diff --git a/lib/Braintree/ResourceCollection.php b/lib/Braintree/ResourceCollection.php index 2a5dd4d..e3b05af 100644 --- a/lib/Braintree/ResourceCollection.php +++ b/lib/Braintree/ResourceCollection.php @@ -153,4 +153,3 @@ public function getIds() return $this->_ids; } } -class_alias('Braintree\ResourceCollection', 'Braintree_ResourceCollection'); diff --git a/lib/Braintree/Result/CreditCardVerification.php b/lib/Braintree/Result/CreditCardVerification.php index c325755..065c1b0 100644 --- a/lib/Braintree/Result/CreditCardVerification.php +++ b/lib/Braintree/Result/CreditCardVerification.php @@ -2,7 +2,9 @@ namespace Braintree\Result; use Braintree\RiskData; +use Braintree\ThreeDSecureInfo; use Braintree\Util; +use Braintree\Base; /** * Braintree Credit Card Verification Result @@ -14,14 +16,14 @@ * @package Braintree * @subpackage Result * - * @property-read string $avsErrorResponseCode + * @property-read string|null $avsErrorResponseCode * @property-read string $avsPostalCodeResponseCode * @property-read string $avsStreetAddressResponseCode * @property-read string $cvvResponseCode * @property-read string $status * */ -class CreditCardVerification +class CreditCardVerification extends Base { // Status const FAILED = 'failed'; @@ -29,7 +31,6 @@ class CreditCardVerification const PROCESSOR_DECLINED = 'processor_declined'; const VERIFIED = 'verified'; - private $_attributes; private $_amount; private $_avsErrorResponseCode; private $_avsPostalCodeResponseCode; @@ -61,6 +62,14 @@ private function _initializeFromArray($attributes) $attributes['riskData'] = RiskData::factory($attributes['riskData']); } + if(isset($attributes['globalId'])) + { + $attributes['graphQLId'] = $attributes['globalId']; + } + + if(isset($attributes['threeDSecureInfo'])) { + $attributes['threeDSecureInfo'] = ThreeDSecureInfo::factory($attributes['threeDSecureInfo']); + } $this->_attributes = $attributes; foreach($attributes AS $name => $value) { $varName = "_$name"; @@ -97,4 +106,3 @@ public static function allStatuses() ]; } } -class_alias('Braintree\Result\CreditCardVerification', 'Braintree_Result_CreditCardVerification'); diff --git a/lib/Braintree/Result/Error.php b/lib/Braintree/Result/Error.php index c0d8ba7..f1ed703 100644 --- a/lib/Braintree/Result/Error.php +++ b/lib/Braintree/Result/Error.php @@ -120,4 +120,3 @@ public function __toString() return __CLASS__ .'[' . $output . ']'; } } -class_alias('Braintree\Result\Error', 'Braintree_Result_Error'); diff --git a/lib/Braintree/Result/Successful.php b/lib/Braintree/Result/Successful.php index 69f087c..68076f5 100644 --- a/lib/Braintree/Result/Successful.php +++ b/lib/Braintree/Result/Successful.php @@ -89,4 +89,3 @@ private function _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn) return array_combine($propertyNames, $objsToReturn); } } -class_alias('Braintree\Result\Successful', 'Braintree_Result_Successful'); diff --git a/lib/Braintree/Result/UsBankAccountVerification.php b/lib/Braintree/Result/UsBankAccountVerification.php index 3c94c9b..cc28856 100644 --- a/lib/Braintree/Result/UsBankAccountVerification.php +++ b/lib/Braintree/Result/UsBankAccountVerification.php @@ -4,6 +4,7 @@ use Braintree\RiskData; use Braintree\Util; use Braintree\UsBankAccount; +use Braintree\Base; /** * Braintree US Bank Account Verification Result @@ -22,7 +23,7 @@ * @property-read Braintree\UsBankAccount $usBankAccount * */ -class UsBankAccountVerification +class UsBankAccountVerification extends Base { // Status const FAILED = 'failed'; @@ -36,7 +37,6 @@ class UsBankAccountVerification const INDEPENDENT_CHECK = 'independent_check'; const MICRO_TRANSFERS = 'micro_transfers'; - private $_attributes; private $_gatewayRejectionReason; private $_status; @@ -109,4 +109,3 @@ public static function allVerificationMethods() ]; } } -class_alias('Braintree\Result\UsBankAccountVerification', 'Braintree_Result_UsBankAccountVerification'); diff --git a/lib/Braintree/RevokedPaymentMethodMetadata.php b/lib/Braintree/RevokedPaymentMethodMetadata.php new file mode 100644 index 0000000..8e5ac3e --- /dev/null +++ b/lib/Braintree/RevokedPaymentMethodMetadata.php @@ -0,0 +1,52 @@ +== More information == + * + * + * @package Braintree + * @category Resources + * + * @property-read string $customerId + * @property-read string $token + * @property-read string $revokedPaymentMethod + */ +class RevokedPaymentMethodMetadata extends Base +{ + /** + * factory method: returns an instance of RevokedPaymentMethodMetadata + * to the requesting method, with populated properties + * + * @ignore + * @return RevokedPaymentMethodMetadata + */ + public static function factory($attributes) + { + $instance = new self(); + $instance->revokedPaymentMethod = PaymentMethodParser::parsePaymentMethod($attributes); + $instance->customerId = $instance->revokedPaymentMethod->customerId; + $instance->token = $instance->revokedPaymentMethod->token; + return $instance; + } + + /** + * create a printable representation of the object as: + * ClassName[property=value, property=value] + * @return string + */ + public function __toString() + { + return __CLASS__ . '[' . + Util::attributesToString($this->_attributes) . ']'; + } +} diff --git a/lib/Braintree/RiskData.php b/lib/Braintree/RiskData.php index 971d805..affc737 100644 --- a/lib/Braintree/RiskData.php +++ b/lib/Braintree/RiskData.php @@ -1,6 +1,11 @@ settlementBatchSummary()->generate($settlement_date, $groupByCustomField); } } -class_alias('Braintree\SettlementBatchSummary', 'Braintree_SettlementBatchSummary'); diff --git a/lib/Braintree/SettlementBatchSummaryGateway.php b/lib/Braintree/SettlementBatchSummaryGateway.php index e70db87..61c4a75 100644 --- a/lib/Braintree/SettlementBatchSummaryGateway.php +++ b/lib/Braintree/SettlementBatchSummaryGateway.php @@ -103,4 +103,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\SettlementBatchSummaryGateway', 'Braintree_SettlementBatchSummaryGateway'); diff --git a/lib/Braintree/SignatureService.php b/lib/Braintree/SignatureService.php index 5e12369..29d2448 100644 --- a/lib/Braintree/SignatureService.php +++ b/lib/Braintree/SignatureService.php @@ -21,4 +21,3 @@ public function hash($data) } } -class_alias('Braintree\SignatureService', 'Braintree_SignatureService'); diff --git a/lib/Braintree/Subscription.php b/lib/Braintree/Subscription.php index b4731a2..6aa28bd 100644 --- a/lib/Braintree/Subscription.php +++ b/lib/Braintree/Subscription.php @@ -8,9 +8,38 @@ * * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} * - * PHP Version 5 - * * @package Braintree + * + * @property-read \Braintree\Addon[] $addOns + * @property-read string $balance + * @property-read int $billingDayOfMonth + * @property-read \DateTime $billingPeriodEndDate + * @property-read \DateTime $billingPeriodStartDate + * @property-read \DateTime $createdAt + * @property-read int $currentBillingCycle + * @property-read int|null $daysPastDue + * @property-read string|null $description + * @property-read \Braintree\Descriptor|null $descriptor + * @property-read \Braintree\Discount[] $discounts + * @property-read int $failureCount + * @property-read \DateTime $firstBillingDate + * @property-read string $id + * @property-read string $merchantAccountId + * @property-read boolean $neverExpires + * @property-read string $nextBillingPeriodAmount + * @property-read \DateTime $nextBillingDate + * @property-read int|null $numberOfBillingCycles + * @property-read \DateTime|null $paidThroughDate + * @property-read string $paymentMethodToken + * @property-read string $planId + * @property-read string $price + * @property-read string $status + * @property-read \Braintree\Subscription\StatusDetails[] $statusHistory + * @property-read \Braintree\Transaction[] $transactions + * @property-read int $trialDuration + * @property-read string $trialDurationUnit + * @property-read boolean $trialPeriod + * @property-read \DateTime $updatedAt */ class Subscription extends Base { @@ -141,4 +170,3 @@ public static function cancel($subscriptionId) return Configuration::gateway()->subscription()->cancel($subscriptionId); } } -class_alias('Braintree\Subscription', 'Braintree_Subscription'); diff --git a/lib/Braintree/Subscription/StatusDetails.php b/lib/Braintree/Subscription/StatusDetails.php index cfd2bda..d6146dc 100644 --- a/lib/Braintree/Subscription/StatusDetails.php +++ b/lib/Braintree/Subscription/StatusDetails.php @@ -14,11 +14,10 @@ * @property-read string $planId * @property-read string $balance * @property-read string $status - * @property-read string $timestamp + * @property-read \DateTime $timestamp * @property-read string $subscriptionSource * @property-read string $user */ class StatusDetails extends Instance { } -class_alias('Braintree\Subscription\StatusDetails', 'Braintree_Subscription_StatusDetails'); diff --git a/lib/Braintree/SubscriptionGateway.php b/lib/Braintree/SubscriptionGateway.php index 1d366c5..292a9c0 100644 --- a/lib/Braintree/SubscriptionGateway.php +++ b/lib/Braintree/SubscriptionGateway.php @@ -10,8 +10,6 @@ * * For more detailed information on Subscriptions, see {@link https://developers.braintreepayments.com/reference/response/subscription/php https://developers.braintreepayments.com/reference/response/subscription/php} * - * PHP Version 5 - * * @package Braintree */ class SubscriptionGateway @@ -223,4 +221,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\SubscriptionGateway', 'Braintree_SubscriptionGateway'); diff --git a/lib/Braintree/SubscriptionSearch.php b/lib/Braintree/SubscriptionSearch.php index ba2a5ef..1b272d8 100644 --- a/lib/Braintree/SubscriptionSearch.php +++ b/lib/Braintree/SubscriptionSearch.php @@ -69,4 +69,3 @@ public static function createdAt() return new RangeNode('created_at'); } } -class_alias('Braintree\SubscriptionSearch', 'Braintree_SubscriptionSearch'); diff --git a/lib/Braintree/Test/AuthenticationIds.php b/lib/Braintree/Test/AuthenticationIds.php new file mode 100644 index 0000000..6ae7756 --- /dev/null +++ b/lib/Braintree/Test/AuthenticationIds.php @@ -0,0 +1,37 @@ +testing()->settlementPending($transactionId); } } -class_alias('Braintree\Test\Transaction', 'Braintree_Test_Transaction'); diff --git a/lib/Braintree/Test/TransactionAmounts.php b/lib/Braintree/Test/TransactionAmounts.php index 592d70d..bf45990 100644 --- a/lib/Braintree/Test/TransactionAmounts.php +++ b/lib/Braintree/Test/TransactionAmounts.php @@ -12,7 +12,7 @@ */ class TransactionAmounts { - public static $authorize = '1000.00'; - public static $decline = '2000.00'; + public static $authorize = '1000.00'; + public static $decline = '2000.00'; + public static $hardDecline = '2015.00'; } -class_alias('Braintree\Test\TransactionAmounts', 'Braintree_Test_TransactionAmounts'); diff --git a/lib/Braintree/Test/VenmoSdk.php b/lib/Braintree/Test/VenmoSdk.php index 34b8fc2..c0b4feb 100644 --- a/lib/Braintree/Test/VenmoSdk.php +++ b/lib/Braintree/Test/VenmoSdk.php @@ -27,4 +27,3 @@ public static function getInvalidTestSession() { return "stub-invalid-session"; } } -class_alias('Braintree\Test\VenmoSdk', 'Braintree_Test_VenmoSdk'); diff --git a/lib/Braintree/TestingGateway.php b/lib/Braintree/TestingGateway.php index a7626b6..a1d4635 100644 --- a/lib/Braintree/TestingGateway.php +++ b/lib/Braintree/TestingGateway.php @@ -49,4 +49,3 @@ private function _checkEnvironment() } } } -class_alias('Braintree\TestingGateway', 'Braintree_TestingGateway'); diff --git a/lib/Braintree/TextNode.php b/lib/Braintree/TextNode.php index 9f932a3..f8a9a5a 100644 --- a/lib/Braintree/TextNode.php +++ b/lib/Braintree/TextNode.php @@ -9,4 +9,3 @@ public function contains($value) return $this; } } -class_alias('Braintree\TextNode', 'Braintree_TextNode'); diff --git a/lib/Braintree/ThreeDSecureInfo.php b/lib/Braintree/ThreeDSecureInfo.php index a04ec39..0008019 100644 --- a/lib/Braintree/ThreeDSecureInfo.php +++ b/lib/Braintree/ThreeDSecureInfo.php @@ -1,6 +1,17 @@ _set('coinbaseDetails', - new Transaction\CoinbaseDetails( - $transactionAttribs['coinbaseAccount'] - ) - ); - } - if (isset($transactionAttribs['usBankAccount'])) { $this->_set('usBankAccount', new Transaction\UsBankAccountDetails( @@ -318,14 +357,6 @@ protected function _initialize($transactionAttribs) ); } - if (isset($transactionAttribs['idealPayment'])) { - $this->_set('idealPayment', - new Transaction\IdealPaymentDetails( - $transactionAttribs['idealPayment'] - ) - ); - } - if (isset($transactionAttribs['paypal'])) { $this->_set('paypalDetails', new Transaction\PayPalDetails( @@ -334,6 +365,22 @@ protected function _initialize($transactionAttribs) ); } + if (isset($transactionAttribs['paypalHere'])) { + $this->_set('paypalHereDetails', + new Transaction\PayPalHereDetails( + $transactionAttribs['paypalHere'] + ) + ); + } + + if (isset($transactionAttribs['localPayment'])) { + $this->_set('localPaymentDetails', + new Transaction\LocalPaymentDetails( + $transactionAttribs['localPayment'] + ) + ); + } + if (isset($transactionAttribs['customer'])) { $this->_set('customerDetails', new Transaction\CustomerDetails( @@ -485,7 +532,7 @@ public function vaultCustomer() } } - /** @return bool */ + /** @return boolean */ public function isDisbursed() { return $this->disbursementDetails->isValid(); } @@ -517,11 +564,6 @@ public static function cloneTransaction($transactionId, $attribs) return Configuration::gateway()->transaction()->cloneTransaction($transactionId, $attribs); } - public static function createFromTransparentRedirect($queryString) - { - return Configuration::gateway()->transaction()->createFromTransparentRedirect($queryString); - } - public static function createTransactionUrl() { return Configuration::gateway()->transaction()->createTransactionUrl(); @@ -612,4 +654,3 @@ public static function refund($transactionId, $amount = null) return Configuration::gateway()->transaction()->refund($transactionId, $amount); } } -class_alias('Braintree\Transaction', 'Braintree_Transaction'); diff --git a/lib/Braintree/Transaction/AddressDetails.php b/lib/Braintree/Transaction/AddressDetails.php index 597a208..d5770da 100644 --- a/lib/Braintree/Transaction/AddressDetails.php +++ b/lib/Braintree/Transaction/AddressDetails.php @@ -24,4 +24,3 @@ class AddressDetails extends Instance { protected $_attributes = []; } -class_alias('Braintree\Transaction\AddressDetails', 'Braintree_Transaction_AddressDetails'); diff --git a/lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php b/lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php index a5a29ac..5b99a1f 100644 --- a/lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php +++ b/lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php @@ -40,4 +40,3 @@ public function __construct($attributes) parent::__construct($attributes); } } -class_alias('Braintree\Transaction\AmexExpressCheckoutCardDetails', 'Braintree_Transaction_AmexExpressCheckoutCardDetails'); diff --git a/lib/Braintree/Transaction/AndroidPayCardDetails.php b/lib/Braintree/Transaction/AndroidPayCardDetails.php index a3a52c5..c267c30 100644 --- a/lib/Braintree/Transaction/AndroidPayCardDetails.php +++ b/lib/Braintree/Transaction/AndroidPayCardDetails.php @@ -18,11 +18,21 @@ * @subpackage Transaction * * @property-read string $bin + * @property-read string $commercial + * @property-read string $countryOfIssuance + * @property-read string $debit * @property-read string $default + * @property-read string $durbinRegulated * @property-read string $expirationMonth * @property-read string $expirationYear * @property-read string $googleTransactionId + * @property-read string $healthcare * @property-read string $imageUrl + * @property-read boolean $isNetworkTokenized + * @property-read string $issuingBank + * @property-read string $payroll + * @property-read string $prepaid + * @property-read string $productId * @property-read string $sourceCardLast4 * @property-read string $sourceCardType * @property-read string $sourceDescription @@ -44,4 +54,3 @@ public function __construct($attributes) $this->_attributes['last4'] = $this->virtualCardLast4; } } -class_alias('Braintree\Transaction\AndroidPayCardDetails', 'Braintree_Transaction_AndroidPayCardDetails'); diff --git a/lib/Braintree/Transaction/ApplePayCardDetails.php b/lib/Braintree/Transaction/ApplePayCardDetails.php index f0a2be4..eb4b333 100644 --- a/lib/Braintree/Transaction/ApplePayCardDetails.php +++ b/lib/Braintree/Transaction/ApplePayCardDetails.php @@ -17,11 +17,21 @@ * @package Braintree * @subpackage Transaction * + * @property-read string $bin * @property-read string $cardType - * @property-read string $paymentInstrumentName + * @property-read string $cardholderName + * @property-read string $commercial + * @property-read string $country_of_issuance + * @property-read string $debit + * @property-read string $durbin_regulated * @property-read string $expirationMonth * @property-read string $expirationYear - * @property-read string $cardholderName + * @property-read string $healthcare + * @property-read string $issuing_bank + * @property-read string $paymentInstrumentName + * @property-read string $payroll + * @property-read string $prepaid + * @property-read string $product_id * @property-read string $sourceDescription */ class ApplePayCardDetails extends Instance @@ -36,4 +46,3 @@ public function __construct($attributes) parent::__construct($attributes); } } -class_alias('Braintree\Transaction\ApplePayCardDetails', 'Braintree_Transaction_ApplePayCardDetails'); diff --git a/lib/Braintree/Transaction/CoinbaseDetails.php b/lib/Braintree/Transaction/CoinbaseDetails.php deleted file mode 100644 index 60c1526..0000000 --- a/lib/Braintree/Transaction/CoinbaseDetails.php +++ /dev/null @@ -1,38 +0,0 @@ -achMandate = $achMandate; } } -class_alias('Braintree\Transaction\UsBankAccountDetails', 'Braintree_Transaction_UsBankAccountDetails'); diff --git a/lib/Braintree/Transaction/VenmoAccountDetails.php b/lib/Braintree/Transaction/VenmoAccountDetails.php index b48baed..cbe6142 100644 --- a/lib/Braintree/Transaction/VenmoAccountDetails.php +++ b/lib/Braintree/Transaction/VenmoAccountDetails.php @@ -35,4 +35,3 @@ public function __construct($attributes) parent::__construct($attributes); } } -class_alias('Braintree\Transaction\VenmoAccountDetails', 'Braintree_Transaction_VenmoAccountDetails'); diff --git a/lib/Braintree/Transaction/VisaCheckoutCardDetails.php b/lib/Braintree/Transaction/VisaCheckoutCardDetails.php index 723b374..d5bfee9 100644 --- a/lib/Braintree/Transaction/VisaCheckoutCardDetails.php +++ b/lib/Braintree/Transaction/VisaCheckoutCardDetails.php @@ -49,4 +49,3 @@ public function __construct($attributes) } } -class_alias('Braintree\Transaction\VisaCheckoutCardDetails', 'Braintree_Transaction_VisaCheckoutCardDetails'); diff --git a/lib/Braintree/TransactionGateway.php b/lib/Braintree/TransactionGateway.php index 6d3d739..596146e 100644 --- a/lib/Braintree/TransactionGateway.php +++ b/lib/Braintree/TransactionGateway.php @@ -60,37 +60,6 @@ private function createNoValidate($attribs) $result = $this->create($attribs); return Util::returnObjectOrThrowException(__CLASS__, $result); } - /** - * - * @deprecated since version 2.3.0 - * @access public - * @param array $attribs - * @return object - */ - public function createFromTransparentRedirect($queryString) - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - return $this->_doCreate( - '/transactions/all/confirm_transparent_redirect_request', - ['id' => $params['id']] - ); - } - /** - * - * @deprecated since version 2.3.0 - * @access public - * @param none - * @return string - */ - public function createTransactionUrl() - { - trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); - return $this->_config->baseUrl() . $this->_config->merchantPath() . - '/transactions/all/create_via_transparent_redirect_request'; - } public static function cloneSignature() { @@ -127,6 +96,7 @@ public static function createSignature() 'taxAmount', 'taxExempt', 'threeDSecureToken', + 'threeDSecureAuthenticationId', 'transactionSource', 'type', 'venmoSdkPaymentMethodCode', @@ -162,7 +132,12 @@ public static function createSignature() [ 'eciFlag', 'cavv', - 'xid'], + 'xid', + 'threeDSecureVersion', + 'authenticationResponse', + 'directoryResponse', + 'cavvAlgorithm', + 'dsTransactionId'], ], ['options' => [ @@ -178,11 +153,10 @@ public static function createSignature() 'skipAdvancedFraudChecking', 'skipAvs', 'skipCvv', - ['threeDSecure' => - ['required'] + ['creditCard' => + ['accountType'] ], - # TODO: Snake case version included for backwards compatiblity. Remove in the next major version - ['three_d_secure' => + ['threeDSecure' => ['required'] ], ['paypal' => @@ -204,8 +178,6 @@ public static function createSignature() ], ['venmo' => [ - # TODO: Snake case version included for backwards compatiblity. Remove in the next major version - 'profile_id', 'profileId' ] ] @@ -213,10 +185,7 @@ public static function createSignature() ], ['customFields' => ['_anyKey_']], ['descriptor' => ['name', 'phone', 'url']], - ['paypalAccount' => ['payeeId', 'payeeEmail']], - # TODO: Snake case version included for backwards compatiblity. Remove in the next major version - ['apple_pay_card' => ['number', 'cardholder_name', 'cryptogram', 'expiration_month', 'expiration_year', 'eci_indicator']], - + ['paypalAccount' => ['payeeId', 'payeeEmail', 'payerId', 'paymentId']], ['applePayCard' => ['number', 'cardholderName', 'cryptogram', 'expirationMonth', 'expirationYear', 'eciIndicator']], ['industry' => ['industryType', @@ -230,7 +199,53 @@ public static function createSignature() 'lodgingCheckInDate', 'lodgingCheckOutDate', 'lodgingName', - 'roomRate' + 'roomRate', + 'roomTax', + 'passengerFirstName', + 'passengerLastName', + 'passengerMiddleInitial', + 'passengerTitle', + 'issuedDate', + 'travelAgencyName', + 'travelAgencyCode', + 'ticketNumber', + 'issuingCarrierCode', + 'customerCode', + 'fareAmount', + 'feeAmount', + 'taxAmount', + 'restrictedTicket', + 'noShow', + 'advancedDeposit', + 'fireSafe', + 'propertyPhone', + ['legs' => + [ + 'conjunctionTicket', + 'exchangeTicket', + 'couponNumber', + 'serviceClass', + 'carrierCode', + 'fareBasisCode', + 'flightNumber', + 'departureDate', + 'departureAirportCode', + 'departureTime', + 'arrivalAirportCode', + 'arrivalTime', + 'stopoverPermitted', + 'fareAmount', + 'feeAmount', + 'taxAmount', + 'endorsementOrRestrictions' + ] + ], + ['additionalCharges' => + [ + 'kind', + 'amount' + ] + ] ] ] ] @@ -244,7 +259,15 @@ public static function createSignature() public static function submitForSettlementSignature() { - return ['orderId', ['descriptor' => ['name', 'phone', 'url']]]; + return ['orderId', ['descriptor' => ['name', 'phone', 'url']], + 'purchaseOrderNumber', + 'taxAmount', + 'taxExempt', + 'shippingAmount', + 'discountAmount', + 'shipsFromPostalCode', + ['lineItems' => ['quantity', 'name', 'description', 'kind', 'unitAmount', 'unitTaxAmount', 'totalAmount', 'discountAmount', 'taxAmount', 'unitOfMeasure', 'productCode', 'commodityCode', 'url']], + ]; } public static function updateDetailsSignature() @@ -352,7 +375,7 @@ public function search($query) return new ResourceCollection($response, $pager); } else { - throw new Exception\DownForMaintenance(); + throw new Exception\RequestTimeout(); } } @@ -372,7 +395,7 @@ public function fetch($query, $ids) 'transaction' ); } else { - throw new Exception\DownForMaintenance(); + throw new Exception\RequestTimeout(); } } @@ -511,11 +534,6 @@ private function _validateId($id = null) { 'expected transaction id to be set' ); } - if (!preg_match('/^[0-9a-z]+$/', $id)) { - throw new InvalidArgumentException( - $id . ' is an invalid transaction id.' - ); - } } /** @@ -547,4 +565,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\TransactionGateway', 'Braintree_TransactionGateway'); diff --git a/lib/Braintree/TransactionLineItem.php b/lib/Braintree/TransactionLineItem.php index 39ae828..ad4a04b 100644 --- a/lib/Braintree/TransactionLineItem.php +++ b/lib/Braintree/TransactionLineItem.php @@ -15,22 +15,23 @@ * * @package Braintree * - * @property-read string $quantity - * @property-read string $name + * @property-read string $commodityCode * @property-read string $description + * @property-read string $discountAmount * @property-read string $kind - * @property-read string $unitAmount - * @property-read string $unitTaxAmount + * @property-read string $name + * @property-read string $productCode + * @property-read string $quantity + * @property-read string $taxAmount * @property-read string $totalAmount - * @property-read string $discountAmount + * @property-read string $unitAmount * @property-read string $unitOfMeasure - * @property-read string $productCode - * @property-read string $commodityCode + * @property-read string $unitTaxAmount * @property-read string $url */ class TransactionLineItem extends Instance { - // LineItem Kinds + // TransactionLineItem Kinds const CREDIT = 'credit'; const DEBIT = 'debit'; @@ -49,6 +50,3 @@ public static function findAll($transactionId) return Configuration::gateway()->transactionLineItem()->findAll($transactionId); } } -class_alias('Braintree\TransactionLineItem', 'Braintree_TransactionLineItem'); -class_alias('Braintree\TransactionLineItem', 'Braintree\Transaction\LineItem'); -class_alias('Braintree\TransactionLineItem', 'Braintree_Transaction_LineItem'); diff --git a/lib/Braintree/TransactionLineItemGateway.php b/lib/Braintree/TransactionLineItemGateway.php index 7b1db2f..3521c30 100644 --- a/lib/Braintree/TransactionLineItemGateway.php +++ b/lib/Braintree/TransactionLineItemGateway.php @@ -64,4 +64,3 @@ private function _validateId($id = null) { } } } -class_alias('Braintree\TransactionLineItemGateway', 'Braintree_TransactionLineItemGateway'); diff --git a/lib/Braintree/TransactionSearch.php b/lib/Braintree/TransactionSearch.php index 5271b0b..9711fa1 100644 --- a/lib/Braintree/TransactionSearch.php +++ b/lib/Braintree/TransactionSearch.php @@ -31,7 +31,6 @@ public static function customerPhone() { return new TextNode('custo public static function customerWebsite() { return new TextNode('customer_website'); } public static function disbursementDate() { return new RangeNode("disbursementDate"); } public static function disputeDate() { return new RangeNode("disputeDate"); } - public static function europeBankAccountIban() { return new TextNode("europeBankAccountIban"); } public static function failedAt() { return new RangeNode("failedAt"); } public static function gatewayRejectedAt() { return new RangeNode("gatewayRejectedAt"); } public static function id() { return new TextNode('id'); } @@ -128,4 +127,3 @@ public static function type() ]); } } -class_alias('Braintree\TransactionSearch', 'Braintree_TransactionSearch'); diff --git a/lib/Braintree/TransparentRedirect.php b/lib/Braintree/TransparentRedirect.php deleted file mode 100644 index 30f274d..0000000 --- a/lib/Braintree/TransparentRedirect.php +++ /dev/null @@ -1,100 +0,0 @@ - - * $trData = TransparentRedirect::createCustomerData(array( - * 'redirectUrl => 'http://example.com/redirect_back_to_merchant_site', - * )); - * - * - * In addition to the redirectUrl, any data that needs to be protected - * from user tampering should be included in the trData. - * For example, to prevent the user from tampering with the transaction - * amount, include the amount in the trData. - * - * - * $trData = TransparentRedirect::transactionData(array( - * 'redirectUrl' => 'http://example.com/complete_transaction', - * 'transaction' => array('amount' => '100.00'), - * )); - * - * - * - * @package Braintree - * @category Resources - */ -class TransparentRedirect -{ - // Request Kinds - const CREATE_TRANSACTION = 'create_transaction'; - const CREATE_PAYMENT_METHOD = 'create_payment_method'; - const UPDATE_PAYMENT_METHOD = 'update_payment_method'; - const CREATE_CUSTOMER = 'create_customer'; - const UPDATE_CUSTOMER = 'update_customer'; - - /** - * @ignore - * don't permit an explicit call of the constructor! - * (like $t = new TransparentRedirect()) - */ - protected function __construct() - { - - } - - - // static methods redirecting to gateway - - public static function confirm($queryString) - { - return Configuration::gateway()->transparentRedirect()->confirm($queryString); - } - - public static function createCreditCardData($params) - { - return Configuration::gateway()->transparentRedirect()->createCreditCardData($params); - } - - public static function createCustomerData($params) - { - return Configuration::gateway()->transparentRedirect()->createCustomerData($params); - } - - public static function url() - { - return Configuration::gateway()->transparentRedirect()->url(); - } - - public static function transactionData($params) - { - return Configuration::gateway()->transparentRedirect()->transactionData($params); - } - - public static function updateCreditCardData($params) - { - return Configuration::gateway()->transparentRedirect()->updateCreditCardData($params); - } - - public static function updateCustomerData($params) - { - return Configuration::gateway()->transparentRedirect()->updateCustomerData($params); - } - - public static function parseAndValidateQueryString($queryString) - { - return Configuration::gateway()->transparentRedirect()->parseAndValidateQueryString($queryString); - } -} -class_alias('Braintree\TransparentRedirect', 'Braintree_TransparentRedirect'); diff --git a/lib/Braintree/TransparentRedirectGateway.php b/lib/Braintree/TransparentRedirectGateway.php deleted file mode 100644 index 3308af0..0000000 --- a/lib/Braintree/TransparentRedirectGateway.php +++ /dev/null @@ -1,289 +0,0 @@ -_gateway = $gateway; - $this->_config = $gateway->config; - $this->_config->assertHasAccessTokenOrKeys(); - } - - /** - * - * @ignore - */ - private static $_transparentRedirectKeys = 'redirectUrl'; - private static $_createCustomerSignature; - private static $_updateCustomerSignature; - private static $_transactionSignature; - private static $_createCreditCardSignature; - private static $_updateCreditCardSignature; - - /** - * create signatures for different call types - * @ignore - */ - public static function init() - { - - self::$_createCustomerSignature = [ - self::$_transparentRedirectKeys, - ['customer' => CustomerGateway::createSignature()], - ]; - self::$_updateCustomerSignature = [ - self::$_transparentRedirectKeys, - 'customerId', - ['customer' => CustomerGateway::updateSignature()], - ]; - self::$_transactionSignature = [ - self::$_transparentRedirectKeys, - ['transaction' => TransactionGateway::createSignature()], - ]; - self::$_createCreditCardSignature = [ - self::$_transparentRedirectKeys, - ['creditCard' => CreditCardGateway::createSignature()], - ]; - self::$_updateCreditCardSignature = [ - self::$_transparentRedirectKeys, - 'paymentMethodToken', - ['creditCard' => CreditCardGateway::updateSignature()], - ]; - } - - public function confirm($queryString) - { - $params = TransparentRedirect::parseAndValidateQueryString( - $queryString - ); - $confirmationKlasses = [ - TransparentRedirect::CREATE_TRANSACTION => 'Braintree\TransactionGateway', - TransparentRedirect::CREATE_CUSTOMER => 'Braintree\CustomerGateway', - TransparentRedirect::UPDATE_CUSTOMER => 'Braintree\CustomerGateway', - TransparentRedirect::CREATE_PAYMENT_METHOD => 'Braintree\CreditCardGateway', - TransparentRedirect::UPDATE_PAYMENT_METHOD => 'Braintree\CreditCardGateway', - ]; - $confirmationGateway = new $confirmationKlasses[$params["kind"]]($this->_gateway); - return $confirmationGateway->_doCreate('/transparent_redirect_requests/' . $params['id'] . '/confirm', []); - } - - /** - * returns the trData string for creating a credit card, - * @param array $params - * @return string - */ - public function createCreditCardData($params) - { - Util::verifyKeys( - self::$_createCreditCardSignature, - $params - ); - $params["kind"] = TransparentRedirect::CREATE_PAYMENT_METHOD; - return $this->_data($params); - } - - /** - * returns the trData string for creating a customer. - * @param array $params - * @return string - */ - public function createCustomerData($params) - { - Util::verifyKeys( - self::$_createCustomerSignature, - $params - ); - $params["kind"] = TransparentRedirect::CREATE_CUSTOMER; - return $this->_data($params); - - } - - public function url() - { - return $this->_config->baseUrl() . $this->_config->merchantPath() . '/transparent_redirect_requests'; - } - - /** - * returns the trData string for creating a transaction - * @param array $params - * @return string - */ - public function transactionData($params) - { - Util::verifyKeys( - self::$_transactionSignature, - $params - ); - $params["kind"] = TransparentRedirect::CREATE_TRANSACTION; - $transactionType = isset($params['transaction']['type']) ? - $params['transaction']['type'] : - null; - if ($transactionType != Transaction::SALE && $transactionType != Transaction::CREDIT) { - throw new InvalidArgumentException( - 'expected transaction[type] of sale or credit, was: ' . - $transactionType - ); - } - - return $this->_data($params); - } - - /** - * Returns the trData string for updating a credit card. - * - * The paymentMethodToken of the credit card to update is required. - * - * - * $trData = TransparentRedirect::updateCreditCardData(array( - * 'redirectUrl' => 'http://example.com/redirect_here', - * 'paymentMethodToken' => 'token123', - * )); - * - * - * @param array $params - * @return string - */ - public function updateCreditCardData($params) - { - Util::verifyKeys( - self::$_updateCreditCardSignature, - $params - ); - if (!isset($params['paymentMethodToken'])) { - throw new InvalidArgumentException( - 'expected params to contain paymentMethodToken.' - ); - } - $params["kind"] = TransparentRedirect::UPDATE_PAYMENT_METHOD; - return $this->_data($params); - } - - /** - * Returns the trData string for updating a customer. - * - * The customerId of the customer to update is required. - * - * - * $trData = TransparentRedirect::updateCustomerData(array( - * 'redirectUrl' => 'http://example.com/redirect_here', - * 'customerId' => 'customer123', - * )); - * - * - * @param array $params - * @return string - */ - public function updateCustomerData($params) - { - Util::verifyKeys( - self::$_updateCustomerSignature, - $params - ); - if (!isset($params['customerId'])) { - throw new InvalidArgumentException( - 'expected params to contain customerId of customer to update' - ); - } - $params["kind"] = TransparentRedirect::UPDATE_CUSTOMER; - return $this->_data($params); - } - - public function parseAndValidateQueryString($queryString) - { - // parse the params into an array - parse_str($queryString, $params); - // remove the hash - $queryStringWithoutHash = null; - if (preg_match('/^(.*)&hash=[a-f0-9]+$/', $queryString, $match)) { - $queryStringWithoutHash = $match[1]; - } - - if($params['http_status'] != '200') { - $message = null; - if(array_key_exists('bt_message', $params)) { - $message = $params['bt_message']; - } - Util::throwStatusCodeException(isset($params['http_status']) ? $params['http_status'] : null, $message); - } - - // recreate the hash and compare it - if ($this->_hash($queryStringWithoutHash) == $params['hash']) { - return $params; - } else { - throw new Exception\ForgedQueryString(); - } - } - - - /** - * - * @ignore - */ - private function _data($params) - { - if (!isset($params['redirectUrl'])) { - throw new InvalidArgumentException( - 'expected params to contain redirectUrl' - ); - } - $params = $this->_underscoreKeys($params); - $now = new DateTime('now', new DateTimeZone('UTC')); - $trDataParams = array_merge($params, - [ - 'api_version' => Configuration::API_VERSION, - 'public_key' => $this->_config->publicKey(), - 'time' => $now->format('YmdHis'), - ] - ); - ksort($trDataParams); - $urlEncodedData = http_build_query($trDataParams, null, "&"); - $signatureService = new SignatureService( - $this->_config->privateKey(), - "Braintree\Digest::hexDigestSha1" - ); - return $signatureService->sign($urlEncodedData); - } - - private function _underscoreKeys($array) - { - foreach($array as $key=>$value) - { - $newKey = Util::camelCaseToDelimiter($key, '_'); - unset($array[$key]); - if (is_array($value)) - { - $array[$newKey] = $this->_underscoreKeys($value); - } - else - { - $array[$newKey] = $value; - } - } - return $array; - } - - /** - * @ignore - */ - private function _hash($string) - { - return Digest::hexDigestSha1($this->_config->privateKey(), $string); - } -} -TransparentRedirectGateway::init(); -class_alias('Braintree\TransparentRedirectGateway', 'Braintree_TransparentRedirectGateway'); diff --git a/lib/Braintree/UnknownPaymentMethod.php b/lib/Braintree/UnknownPaymentMethod.php index 74e7289..c6131d8 100644 --- a/lib/Braintree/UnknownPaymentMethod.php +++ b/lib/Braintree/UnknownPaymentMethod.php @@ -66,4 +66,3 @@ protected function _initialize($unknownPaymentMethodAttribs) } } -class_alias('Braintree\UnknownPaymentMethod', 'Braintree_UnknownPaymentMethod'); diff --git a/lib/Braintree/UsBankAccount.php b/lib/Braintree/UsBankAccount.php index bf86fbe..59da7ff 100644 --- a/lib/Braintree/UsBankAccount.php +++ b/lib/Braintree/UsBankAccount.php @@ -27,7 +27,7 @@ * @property-read string $last4 * @property-read string $bankName * @property-read string $achMandate - * @property-read string $default + * @property-read boolean $default * @property-read boolean $verified */ class UsBankAccount extends Base @@ -114,4 +114,3 @@ public static function sale($token, $transactionAttribs) return Configuration::gateway()->usBankAccount()->sale($token, $transactionAttribs); } } -class_alias('Braintree\UsBankAccount', 'Braintree_UsBankAccount'); diff --git a/lib/Braintree/UsBankAccountGateway.php b/lib/Braintree/UsBankAccountGateway.php index 6e3393c..0dab854 100644 --- a/lib/Braintree/UsBankAccountGateway.php +++ b/lib/Braintree/UsBankAccountGateway.php @@ -103,4 +103,3 @@ private function _verifyGatewayResponse($response) } } } -class_alias('Braintree\UsBankAccountGateway', 'Braintree_UsBankAccountGateway'); diff --git a/lib/Braintree/UsBankAccountVerification.php b/lib/Braintree/UsBankAccountVerification.php index a062a55..32a695c 100644 --- a/lib/Braintree/UsBankAccountVerification.php +++ b/lib/Braintree/UsBankAccountVerification.php @@ -99,4 +99,3 @@ public static function confirmMicroTransferAmounts($token, $amounts) return Configuration::gateway()->usBankAccountVerification()->confirmMicroTransferAmounts($token, $amounts); } } -class_alias('Braintree\UsBankAccountVerification', 'Braintree_UsBankAccountVerification'); diff --git a/lib/Braintree/UsBankAccountVerificationGateway.php b/lib/Braintree/UsBankAccountVerificationGateway.php index 31397ad..ebfe602 100644 --- a/lib/Braintree/UsBankAccountVerificationGateway.php +++ b/lib/Braintree/UsBankAccountVerificationGateway.php @@ -125,5 +125,3 @@ private function _verifyGatewayResponse($response) } } } - -class_alias('Braintree\UsBankAccountVerificationGateway', 'Braintree_UsBankAccountVerificationGateway'); diff --git a/lib/Braintree/UsBankAccountVerificationSearch.php b/lib/Braintree/UsBankAccountVerificationSearch.php index a6336dc..ad4ad53 100644 --- a/lib/Braintree/UsBankAccountVerificationSearch.php +++ b/lib/Braintree/UsBankAccountVerificationSearch.php @@ -61,4 +61,3 @@ public static function accountNumber() return new EndsWithNode("account_number"); } } -class_alias('Braintree\UsBankAccountVerificationSearch', 'Braintree_UsBankAccountVerificationSearch'); diff --git a/lib/Braintree/Util.php b/lib/Braintree/Util.php index 6b921fa..2b350f2 100644 --- a/lib/Braintree/Util.php +++ b/lib/Braintree/Util.php @@ -6,7 +6,6 @@ /** * Braintree Utility methods - * PHP version 5 */ class Util @@ -61,6 +60,9 @@ public static function throwStatusCodeException($statusCode, $message=null) case 404: throw new Exception\NotFound(); break; + case 408; + throw new Exception\RequestTimeout(); + break; case 426: throw new Exception\UpgradeRequired(); break; @@ -70,8 +72,8 @@ public static function throwStatusCodeException($statusCode, $message=null) case 500: throw new Exception\ServerError(); break; - case 503: - throw new Exception\DownForMaintenance(); + case 504; + throw new Exception\GatewayTimeout(); break; default: throw new Exception\Unexpected('Unexpected HTTP_RESPONSE #' . $statusCode); @@ -97,33 +99,26 @@ public static function throwGraphQLResponseException($response) throw new Exception\Unexpected("Unexpected exception:" . $message); } - switch($error["extensions"]["errorClass"]) { - case "VALIDATION": + $errorClass = $error["extensions"]["errorClass"]; + + if ($errorClass == "VALIDATION") { continue; - case "AUTHENTICATION": + } else if ($errorClass == "AUTHENTICATION") { throw new Exception\Authentication(); - break; - case "AUTHORIZATION": + } else if ($errorClass == "AUTHORIZATION") { throw new Exception\Authorization($message); - break; - case "NOT_FOUND": + } else if ($errorClass == "NOT_FOUND") { throw new Exception\NotFound(); - break; - case "UNSUPPORTED_CLIENT": + } else if ($errorClass == "UNSUPPORTED_CLIENT") { throw new Exception\UpgradeRequired(); - break; - case "RESOURCE_LIMIT": + } else if ($errorClass == "RESOURCE_LIMIT") { throw new Exception\TooManyRequests(); - break; - case "INTERNAL": + } else if ($errorClass == "INTERNAL") { throw new Exception\ServerError(); - break; - case "SERVICE_AVAILABILITY": - throw new Exception\DownForMaintenance(); - break; - default: + } else if ($errorClass == "SERVICE_AVAILABILITY") { + throw new Exception\ServiceUnavailable(); + } else { throw new Exception\Unexpected('Unexpected exception ' . $message); - break; } } } @@ -469,4 +464,3 @@ private static function _removeWildcardKeys($validKeys, $invalidKeys) return $invalidKeys; } } -class_alias('Braintree\Util', 'Braintree_Util'); diff --git a/lib/Braintree/VenmoAccount.php b/lib/Braintree/VenmoAccount.php index 735e081..6ccf934 100644 --- a/lib/Braintree/VenmoAccount.php +++ b/lib/Braintree/VenmoAccount.php @@ -12,13 +12,14 @@ * @package Braintree * @category Resources * - * @property-read string $createdAt - * @property-read string $default - * @property-read string $updatedAt + * @property-read \DateTime $createdAt * @property-read string $customerId + * @property-read boolean $default + * @property-read string $imageUrl * @property-read string $sourceDescription + * @property-read \Braintree\Subscription[] $subscriptions * @property-read string $token - * @property-read string $imageUrl + * @property-read \DateTime $updatedAt * @property-read string $username * @property-read string $venmoUserId */ @@ -71,4 +72,3 @@ protected function _initialize($venmoAccountAttribs) $this->_set('subscriptions', $subscriptionArray); } } -class_alias('Braintree\VenmoAccount', 'Braintree_VenmoAccount'); diff --git a/lib/Braintree/Version.php b/lib/Braintree/Version.php index 2616523..1f38b46 100644 --- a/lib/Braintree/Version.php +++ b/lib/Braintree/Version.php @@ -10,8 +10,8 @@ class Version /** * class constants */ - const MAJOR = 3; - const MINOR = 36; + const MAJOR = 5; + const MINOR = 0; const TINY = 0; /** @@ -31,4 +31,3 @@ public static function get() return self::MAJOR . '.' . self::MINOR . '.' . self::TINY; } } -class_alias('Braintree\Version', 'Braintree_Version'); diff --git a/lib/Braintree/VisaCheckoutCard.php b/lib/Braintree/VisaCheckoutCard.php index 4d13c31..a5d4fb6 100644 --- a/lib/Braintree/VisaCheckoutCard.php +++ b/lib/Braintree/VisaCheckoutCard.php @@ -12,23 +12,23 @@ * @package Braintree * @category Resources * - * @property-read string $billingAddress + * @property-read \Braintree\Address $billingAddress * @property-read string $bin * @property-read string $callId * @property-read string $cardType * @property-read string $cardholderName * @property-read string $commercial * @property-read string $countryOfIssuance - * @property-read string $createdAt + * @property-read \DateTime $createdAt * @property-read string $customerId * @property-read string $customerLocation * @property-read string $debit - * @property-read string $default + * @property-read boolean $default * @property-read string $durbinRegulated * @property-read string $expirationDate * @property-read string $expirationMonth * @property-read string $expirationYear - * @property-read string $expired + * @property-read boolean $expired * @property-read string $healthcare * @property-read string $imageUrl * @property-read string $issuingBank @@ -37,10 +37,10 @@ * @property-read string $payroll * @property-read string $prepaid * @property-read string $productId - * @property-read string $subscriptions + * @property-read \Braintree\Subscription[] $subscriptions * @property-read string $token * @property-read string $uniqueNumberIdentifier - * @property-read string $updatedAt + * @property-read \DateTime $updatedAt */ class VisaCheckoutCard extends Base { @@ -151,4 +151,3 @@ public static function factory($attributes) return $instance; } } -class_alias('Braintree\VisaCheckoutCard', 'Braintree_VisaCheckoutCard'); diff --git a/lib/Braintree/WebhookNotification.php b/lib/Braintree/WebhookNotification.php index 05d2cb6..3da7efa 100644 --- a/lib/Braintree/WebhookNotification.php +++ b/lib/Braintree/WebhookNotification.php @@ -20,6 +20,9 @@ class WebhookNotification extends Base const DISPUTE_OPENED = 'dispute_opened'; const DISPUTE_LOST = 'dispute_lost'; const DISPUTE_WON = 'dispute_won'; + const DISPUTE_ACCEPTED = 'dispute_accepted'; + const DISPUTE_DISPUTED = 'dispute_disputed'; + const DISPUTE_EXPIRED = 'dispute_expired'; const PARTNER_MERCHANT_CONNECTED = 'partner_merchant_connected'; const PARTNER_MERCHANT_DISCONNECTED = 'partner_merchant_disconnected'; const PARTNER_MERCHANT_DECLINED = 'partner_merchant_declined'; @@ -28,9 +31,10 @@ class WebhookNotification extends Base const ACCOUNT_UPDATER_DAILY_REPORT = 'account_updater_daily_report'; const CONNECTED_MERCHANT_STATUS_TRANSITIONED = 'connected_merchant_status_transitioned'; const CONNECTED_MERCHANT_PAYPAL_STATUS_CHANGED = 'connected_merchant_paypal_status_changed'; - const IDEAL_PAYMENT_COMPLETE = 'ideal_payment_complete'; - const IDEAL_PAYMENT_FAILED = 'ideal_payment_failed'; - const GRANTED_PAYMENT_INSTRUMENT_UPDATE = 'granted_payment_instrument_update'; + const GRANTOR_UPDATED_GRANTED_PAYMENT_METHOD = 'grantor_updated_granted_payment_method'; + const RECIPIENT_UPDATED_GRANTED_PAYMENT_METHOD = 'recipient_updated_granted_payment_method'; + const GRANTED_PAYMENT_METHOD_REVOKED = 'granted_payment_method_revoked'; + const PAYMENT_METHOD_REVOKED_BY_CUSTOMER = 'payment_method_revoked_by_customer'; const LOCAL_PAYMENT_COMPLETED = "local_payment_completed"; public static function parse($signature, $payload) { @@ -102,14 +106,14 @@ protected function _initialize($attributes) $this->_set('accountUpdaterDailyReport', AccountUpdaterDailyReport::factory($wrapperNode['accountUpdaterDailyReport'])); } - if (isset($wrapperNode['idealPayment'])) { - $this->_set('idealPayment', IdealPayment::factory($wrapperNode['idealPayment'])); - } - if (isset($wrapperNode['grantedPaymentInstrumentUpdate'])) { $this->_set('grantedPaymentInstrumentUpdate', GrantedPaymentInstrumentUpdate::factory($wrapperNode['grantedPaymentInstrumentUpdate'])); } + if (in_array($attributes['kind'], [self::GRANTED_PAYMENT_METHOD_REVOKED, self::PAYMENT_METHOD_REVOKED_BY_CUSTOMER])) { + $this->_set('revokedPaymentMethodMetadata', RevokedPaymentMethodMetadata::factory($wrapperNode)); + } + if (isset($wrapperNode['localPayment'])) { $this->_set('localPaymentCompleted', LocalPaymentCompleted::factory($wrapperNode['localPayment'])); } @@ -120,4 +124,3 @@ protected function _initialize($attributes) } } } -class_alias('Braintree\WebhookNotification', 'Braintree_WebhookNotification'); diff --git a/lib/Braintree/WebhookNotificationGateway.php b/lib/Braintree/WebhookNotificationGateway.php index 17ef2bb..1b5e8d8 100644 --- a/lib/Braintree/WebhookNotificationGateway.php +++ b/lib/Braintree/WebhookNotificationGateway.php @@ -73,5 +73,3 @@ private function _matchingSignature($signaturePairs) return null; } } - -class_alias('Braintree\WebhookNotificationGateway', 'Braintree_WebhookNotificationGateway'); diff --git a/lib/Braintree/WebhookTesting.php b/lib/Braintree/WebhookTesting.php index 350591c..3203d5b 100644 --- a/lib/Braintree/WebhookTesting.php +++ b/lib/Braintree/WebhookTesting.php @@ -8,4 +8,3 @@ public static function sampleNotification($kind, $id, $sourceMerchantId = null) return Configuration::gateway()->webhookTesting()->sampleNotification($kind, $id, $sourceMerchantId); } } -class_alias('Braintree\WebhookTesting', 'Braintree_WebhookTesting'); diff --git a/lib/Braintree/WebhookTestingGateway.php b/lib/Braintree/WebhookTestingGateway.php index ce675c9..1a00b1e 100644 --- a/lib/Braintree/WebhookTestingGateway.php +++ b/lib/Braintree/WebhookTestingGateway.php @@ -73,6 +73,15 @@ private static function _sampleXml($kind, $id, $sourceMerchantId) case WebhookNotification::DISPUTE_WON: $subjectXml = self::_disputeWonSampleXml($id); break; + case WebhookNotification::DISPUTE_ACCEPTED: + $subjectXml = self::_disputeAcceptedSampleXml($id); + break; + case WebhookNotification::DISPUTE_DISPUTED: + $subjectXml = self::_disputeDisputedSampleXml($id); + break; + case WebhookNotification::DISPUTE_EXPIRED: + $subjectXml = self::_disputeExpiredSampleXml($id); + break; case WebhookNotification::SUBSCRIPTION_CHARGED_SUCCESSFULLY: $subjectXml = self::_subscriptionChargedSuccessfullySampleXml($id); break; @@ -85,15 +94,15 @@ private static function _sampleXml($kind, $id, $sourceMerchantId) case WebhookNotification::ACCOUNT_UPDATER_DAILY_REPORT: $subjectXml = self::_accountUpdaterDailyReportSampleXml($id); break; - case WebhookNotification::IDEAL_PAYMENT_COMPLETE: - $subjectXml = self::_idealPaymentCompleteSampleXml($id); - break; - case WebhookNotification::IDEAL_PAYMENT_FAILED: - $subjectXml = self::_idealPaymentFailedSampleXml($id); + case WebhookNotification::GRANTOR_UPDATED_GRANTED_PAYMENT_METHOD: + $subjectXml = self::_grantedPaymentInstrumentUpdateSampleXml(); break; - case WebhookNotification::GRANTED_PAYMENT_INSTRUMENT_UPDATE: + case WebhookNotification::RECIPIENT_UPDATED_GRANTED_PAYMENT_METHOD: $subjectXml = self::_grantedPaymentInstrumentUpdateSampleXml(); break; + case WebhookNotification::PAYMENT_METHOD_REVOKED_BY_CUSTOMER: + $subjectXml = self::_paymentMethodRevokedByCustomerSampleXml($id); + break; case WebhookNotification::LOCAL_PAYMENT_COMPLETED: $subjectXml = self::_localPaymentCompletedSampleXml(); break; @@ -337,6 +346,75 @@ private static function _disputeWonSampleXml($id) "; } + private static function _disputeAcceptedSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + accepted + fraud + ${id} + + ${id} + 250.00 + + 2014-03-21 + + "; + } + + private static function _disputeDisputedSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + disputed + fraud + ${id} + + ${id} + 250.00 + + 2014-03-21 + + "; + } + + private static function _disputeExpiredSampleXml($id) + { + return " + + 250.00 + 250.0 + 245.00 + USD + 2014-03-01 + 2014-03-21 + chargeback + expired + fraud + ${id} + + ${id} + 250.00 + + 2014-03-21 + + "; + } + private static function _subscriptionSampleXml($id) { return " @@ -476,40 +554,6 @@ private static function _connectedMerchantPayPalStatusChangedSampleXml($id) "; } - private static function _idealPaymentCompleteSampleXml($id) - { - return " - - {$id} - COMPLETE - ABCISSUER - ORDERABC - EUR - 10.00 - 2016-11-29T23:27:34.547Z - https://example.com - 1234567890 - - "; - } - - private static function _idealPaymentFailedSampleXml($id) - { - return " - - {$id} - FAILED - ABCISSUER - ORDERABC - EUR - 10.00 - 2016-11-29T23:27:34.547Z - https://example.com - 1234567890 - - "; - } - private static function _grantedPaymentInstrumentUpdateSampleXml() { return " @@ -530,12 +574,42 @@ private static function _grantedPaymentInstrumentUpdateSampleXml() "; } + private static function _paymentMethodRevokedByCustomerSampleXml($id) + { + return " + + a-billing-agreement-id + 2019-01-01T12:00:00Z + a-customer-id + true + name@email.com + cGF5bWVudG1ldGhvZF9jaDZieXNz + https://assets.braintreegateway.com/payment_method_logo/paypal.png?environment=test + + {$id} + 2019-01-02T12:00:00Z + + a-payer-id + + + 2019-01-02T12:00:00Z + + "; + } + private static function _localPaymentCompletedSampleXml() { return " a-payment-id a-payer-id + ee257d98-de40-47e8-96b3-a6954ea7a9a4 + + 1 + authorizing + 10.00 + order1234 + "; } @@ -550,4 +624,3 @@ private static function _timestamp() return $timestamp; } } -class_alias('Braintree\WebhookTestingGateway', 'Braintree_WebhookTestingGateway'); diff --git a/lib/Braintree/Xml.php b/lib/Braintree/Xml.php index e938c40..782a0d1 100644 --- a/lib/Braintree/Xml.php +++ b/lib/Braintree/Xml.php @@ -3,7 +3,6 @@ /** * Braintree Xml parser and generator - * PHP version 5 * superclass for Braintree XML parsing and generation */ class Xml @@ -36,4 +35,3 @@ public static function buildXmlFromArray($array) return Xml\Generator::arrayToXml($array); } } -class_alias('Braintree\Xml', 'Braintree_Xml'); diff --git a/lib/Braintree/Xml/Generator.php b/lib/Braintree/Xml/Generator.php index a8dc3d6..6ae3a94 100644 --- a/lib/Braintree/Xml/Generator.php +++ b/lib/Braintree/Xml/Generator.php @@ -6,10 +6,6 @@ use XMLWriter; use Braintree\Util; -/** - * PHP version 5 - */ - /** * Generates XML output from arrays using PHP's * built-in XMLWriter @@ -146,4 +142,3 @@ private static function _castDateTime($string) } } } -class_alias('Braintree\Xml\Generator', 'Braintree_Xml_Generator'); diff --git a/lib/Braintree/Xml/Parser.php b/lib/Braintree/Xml/Parser.php index 1c0d05e..7218dbb 100644 --- a/lib/Braintree/Xml/Parser.php +++ b/lib/Braintree/Xml/Parser.php @@ -137,4 +137,3 @@ private static function _timestampToUTC($timestamp) return $dateTime; } } -class_alias('Braintree\Xml\Parser', 'Braintree_Xml_Parser'); diff --git a/lib/class.plugify-gform-braintree.php b/lib/class.plugify-gform-braintree.php index 5736021..3b9043b 100644 --- a/lib/class.plugify-gform-braintree.php +++ b/lib/class.plugify-gform-braintree.php @@ -103,10 +103,16 @@ public function authorize( $feed, $submission_data, $form, $entry ) { try { // Configure Braintree environment - Braintree_Configuration::environment( strtolower( $settings['environment'] ) ); - Braintree_Configuration::merchantId( $settings['merchant-id']); - Braintree_Configuration::publicKey( $settings['public-key'] ); - Braintree_Configuration::privateKey( $settings['private-key'] ); + $braintree_config = new \Braintree\Configuration([ + 'environment' => strtolower( $settings['environment'] ) , + 'merchantId' => $settings['merchant-id'], + 'publicKey' => $settings['public-key'], + 'privateKey' => $settings['private-key'] + ]); + + $braintree_config->timeout(60); + + $gateway = new Braintree\Gateway($braintree_config); // Set to auto settlemt if applicable if( $settings['settlement'] == 'Yes' ) { @@ -114,11 +120,11 @@ public function authorize( $feed, $submission_data, $form, $entry ) { } // Send transaction to Braintree - $result = Braintree_Transaction::sale( $args ); + $result = $gateway->transaction()->sale($args); $this->log_debug( "Braintree_Transaction::sale RESPONSE => " . print_r( $result, 1 ) ); // Update response to reflect successful payment - if( $result->success == '1' ) { + if( $result->success ) { do_action('angelleye_gravity_forms_response_data', $result, $submission_data, '16', (strtolower($settings['environment']) == 'sandbox') ? true : false , false, 'braintree'); $authorization['is_authorized'] = true; $authorization['error_message'] = ''; From 72b24ef7eabe9efd1aa3de3d9dbe49d3e565b73e Mon Sep 17 00:00:00 2001 From: Deepak Maurya Date: Tue, 28 Apr 2020 19:32:02 +0530 Subject: [PATCH 61/99] Fixed the No Conflict mode issue with Braintree JS and CSS loading and added notice for Braintree Custom fields, GFB-19 --- assets/css/gravity-forms-braintree-admin.css | 10 ++++++++++ assets/js/gravity-forms-braintree-admin.js | 3 +++ .../angelleye-braintree-field-map-form.php | 19 +++++++++++++++++- lib/class.plugify-gform-braintree.php | 20 +++++++++++++++++-- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/assets/css/gravity-forms-braintree-admin.css b/assets/css/gravity-forms-braintree-admin.css index 3d1d90e..b9469d0 100644 --- a/assets/css/gravity-forms-braintree-admin.css +++ b/assets/css/gravity-forms-braintree-admin.css @@ -72,3 +72,13 @@ -webkit-font-smoothing: antialiased; } +.alert-notification-custom-fields:after,.alert-notification-custom-fields:before { + content:"";display:table;clear:both; +} +.alert-notification-custom-fields{ + padding:0.01em 16px;color:#000!important;background-color:#ffffcc!important;margin-top:16px; +} + +#gform_braintree_mapping table{ + width: 800px; +} \ No newline at end of file diff --git a/assets/js/gravity-forms-braintree-admin.js b/assets/js/gravity-forms-braintree-admin.js index c13f21b..7dc8fa6 100644 --- a/assets/js/gravity-forms-braintree-admin.js +++ b/assets/js/gravity-forms-braintree-admin.js @@ -23,6 +23,9 @@ jQuery(function () { jQuery(document).ready(function ($) { $('.addmorecustomfield').click(function () { $('.custom_field_row:last').after('
'+$('.custom_fields_template').html()+' Remove

Custom Fields Add Custom Field

+

Custom Fields + + + + + Add Custom Field + + + + +

+
+

Please make sure all of the defined custom field names match the Braintree Custom Field API names. Otherwise, the payment processor will return an error.

+
+