Version Notes
Connect your Magento store to Braintree to accept Credit Cards & PayPal using V.Zero SDK
Download this release
Release Info
Developer | Dave Macaulay |
Extension | Gene_Braintree |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions.php +20 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions/Grid.php +350 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions/Search.php +110 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Config.php +81 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Currency.php +57 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Moduleversion.php +95 -0
- app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Version.php +53 -0
- app/code/community/Gene/Braintree/Block/Cart/Totals.php +25 -0
- app/code/community/Gene/Braintree/Block/Creditcard.php +143 -0
- app/code/community/Gene/Braintree/Block/Creditcard/Info.php +127 -0
- app/code/community/Gene/Braintree/Block/Creditcard/Threedsecure.php +26 -0
- app/code/community/Gene/Braintree/Block/Js.php +138 -0
- app/code/community/Gene/Braintree/Block/Paypal.php +96 -0
- app/code/community/Gene/Braintree/Block/Paypal/Info.php +61 -0
- app/code/community/Gene/Braintree/Block/Saved.php +34 -0
- app/code/community/Gene/Braintree/Helper/Data.php +33 -0
- app/code/community/Gene/Braintree/Model/Debug.php +41 -0
- app/code/community/Gene/Braintree/Model/Observer.php +143 -0
- app/code/community/Gene/Braintree/Model/Paymentmethod/Abstract.php +75 -0
- app/code/community/Gene/Braintree/Model/Paymentmethod/Creditcard.php +380 -0
- app/code/community/Gene/Braintree/Model/Paymentmethod/Paypal.php +210 -0
- app/code/community/Gene/Braintree/Model/Saved.php +130 -0
- app/code/community/Gene/Braintree/Model/Source/Cctype.php +28 -0
- app/code/community/Gene/Braintree/Model/Source/Creditcard/CaptureAction.php +34 -0
- app/code/community/Gene/Braintree/Model/Source/Creditcard/PaymentAction.php +31 -0
- app/code/community/Gene/Braintree/Model/Source/Environment.php +28 -0
- app/code/community/Gene/Braintree/Model/Source/Paypal/Locale.php +55 -0
- app/code/community/Gene/Braintree/Model/Source/Paypal/Paymenttype.php +33 -0
- app/code/community/Gene/Braintree/Model/System/Config/Backend/Currency.php +32 -0
- app/code/community/Gene/Braintree/Model/Wrapper/Braintree.php +729 -0
- app/code/community/Gene/Braintree/controllers/Adminhtml/BraintreeController.php +97 -0
- app/code/community/Gene/Braintree/controllers/CheckoutController.php +61 -0
- app/code/community/Gene/Braintree/controllers/SavedController.php +92 -0
- app/code/community/Gene/Braintree/etc/adminhtml.xml +41 -0
- app/code/community/Gene/Braintree/etc/config.xml +191 -0
- app/code/community/Gene/Braintree/etc/system.xml +500 -0
- app/code/community/Gene/Braintree/sql/gene_braintree_setup/install-0.1.0.php +30 -0
- app/design/adminhtml/default/default/layout/gene/braintree.xml +25 -0
- app/design/adminhtml/default/default/template/gene/braintree/creditcard.phtml +135 -0
- app/design/adminhtml/default/default/template/gene/braintree/creditcard/info.phtml +17 -0
- app/design/adminhtml/default/default/template/gene/braintree/js.phtml +63 -0
- app/design/adminhtml/default/default/template/gene/braintree/paypal/info.phtml +17 -0
- app/design/adminhtml/default/default/template/gene/braintree/transactions/index.phtml +12 -0
- app/design/adminhtml/default/default/template/gene/braintree/transactions/search.phtml +101 -0
- app/design/frontend/base/default/layout/gene/braintree.xml +83 -0
- app/design/frontend/base/default/template/gene/braintree/creditcard.phtml +228 -0
- app/design/frontend/base/default/template/gene/braintree/creditcard/info.phtml +20 -0
- app/design/frontend/base/default/template/gene/braintree/creditcard/threedsecure.phtml +2 -0
- app/design/frontend/base/default/template/gene/braintree/customer/methods.phtml +23 -0
- app/design/frontend/base/default/template/gene/braintree/customer/saved.phtml +34 -0
- app/design/frontend/base/default/template/gene/braintree/js/amasty.phtml +375 -0
- app/design/frontend/base/default/template/gene/braintree/js/data.phtml +15 -0
- app/design/frontend/base/default/template/gene/braintree/js/default.phtml +188 -0
- app/design/frontend/base/default/template/gene/braintree/js/idev.phtml +402 -0
- app/design/frontend/base/default/template/gene/braintree/js/setup.phtml +36 -0
- app/design/frontend/base/default/template/gene/braintree/paypal.phtml +106 -0
- app/design/frontend/base/default/template/gene/braintree/paypal/info.phtml +21 -0
- app/etc/modules/Gene_Braintree.xml +9 -0
- app/locale/en_US/Gene_Braintree.csv +121 -0
- js/gene/braintree/braintree.js +5 -0
- js/gene/braintree/vzero.js +753 -0
- lib/Braintree.php +194 -0
- lib/Braintree/AddOn.php +18 -0
- lib/Braintree/AddOnGateway.php +27 -0
- lib/Braintree/Address.php +116 -0
- lib/Braintree/AddressGateway.php +286 -0
- lib/Braintree/ApplePayCard.php +95 -0
- lib/Braintree/ClientToken.php +29 -0
- lib/Braintree/ClientTokenGateway.php +90 -0
- lib/Braintree/CoinbaseAccount.php +108 -0
- lib/Braintree/Collection.php +153 -0
- lib/Braintree/Configuration.php +329 -0
- lib/Braintree/CreditCard.php +292 -0
- lib/Braintree/CreditCardGateway.php +471 -0
- lib/Braintree/CreditCardVerification.php +22 -0
- lib/Braintree/CreditCardVerificationGateway.php +48 -0
- lib/Braintree/CreditCardVerificationSearch.php +33 -0
- lib/Braintree/Customer.php +262 -0
- lib/Braintree/CustomerGateway.php +594 -0
- lib/Braintree/CustomerSearch.php +31 -0
- lib/Braintree/Descriptor.php +4 -0
- lib/Braintree/Digest.php +59 -0
- lib/Braintree/Disbursement.php +49 -0
- lib/Braintree/DisbursementDetails.php +25 -0
- lib/Braintree/Discount.php +18 -0
- lib/Braintree/DiscountGateway.php +27 -0
- lib/Braintree/Dispute.php +75 -0
- lib/Braintree/Dispute/TransactionDetails.php +22 -0
- lib/Braintree/EqualityNode.php +10 -0
- lib/Braintree/Error/Codes.php +457 -0
- lib/Braintree/Error/ErrorCollection.php +109 -0
- lib/Braintree/Error/Validation.php +56 -0
- lib/Braintree/Error/ValidationErrorCollection.php +127 -0
- lib/Braintree/Exception.php +11 -0
- lib/Braintree/Exception/Authentication.php +13 -0
- lib/Braintree/Exception/Authorization.php +15 -0
- lib/Braintree/Exception/Configuration.php +12 -0
- lib/Braintree/Exception/DownForMaintenance.php +12 -0
- lib/Braintree/Exception/ForgedQueryString.php +16 -0
- lib/Braintree/Exception/InvalidSignature.php +5 -0
- lib/Braintree/Exception/NotFound.php +12 -0
- lib/Braintree/Exception/SSLCaFileNotFound.php +12 -0
- lib/Braintree/Exception/SSLCertificate.php +12 -0
- lib/Braintree/Exception/ServerError.php +12 -0
- lib/Braintree/Exception/Unexpected.php +13 -0
- lib/Braintree/Exception/UpgradeRequired.php +12 -0
- lib/Braintree/Exception/ValidationsFailed.php +12 -0
- lib/Braintree/Gateway.php +101 -0
- lib/Braintree/Http.php +106 -0
- lib/Braintree/Instance.php +72 -0
- lib/Braintree/IsNode.php +21 -0
- lib/Braintree/KeyValueNode.php +22 -0
- lib/Braintree/MerchantAccount.php +62 -0
- lib/Braintree/MerchantAccount/AddressDetails.php +5 -0
- lib/Braintree/MerchantAccount/BusinessDetails.php +19 -0
- lib/Braintree/MerchantAccount/FundingDetails.php +6 -0
- lib/Braintree/MerchantAccount/IndividualDetails.php +19 -0
- lib/Braintree/MerchantAccountGateway.php +151 -0
- lib/Braintree/Modification.php +23 -0
- lib/Braintree/MultipleValueNode.php +37 -0
- lib/Braintree/MultipleValueOrTextNode.php +45 -0
- lib/Braintree/PartialMatchNode.php +16 -0
- lib/Braintree/PartnerMerchant.php +40 -0
- lib/Braintree/PayPalAccount.php +107 -0
- lib/Braintree/PayPalAccountGateway.php +174 -0
- lib/Braintree/PaymentInstrumentType.php +9 -0
- lib/Braintree/PaymentMethod.php +44 -0
- lib/Braintree/PaymentMethodGateway.php +251 -0
- lib/Braintree/PaymentMethodNonce.php +46 -0
- lib/Braintree/PaymentMethodNonceGateway.php +46 -0
- lib/Braintree/Plan.php +48 -0
- lib/Braintree/PlanGateway.php +30 -0
- lib/Braintree/RangeNode.php +38 -0
- lib/Braintree/ResourceCollection.php +141 -0
- lib/Braintree/Result/CreditCardVerification.php +84 -0
- lib/Braintree/Result/Error.php +109 -0
- lib/Braintree/Result/Successful.php +74 -0
- lib/Braintree/RiskData.php +27 -0
- lib/Braintree/SettlementBatchSummary.php +31 -0
- lib/Braintree/SettlementBatchSummaryGateway.php +66 -0
- lib/Braintree/SignatureService.php +22 -0
- lib/Braintree/Subscription.php +138 -0
- lib/Braintree/Subscription/StatusDetails.php +19 -0
- lib/Braintree/SubscriptionGateway.php +209 -0
- lib/Braintree/SubscriptionSearch.php +64 -0
- lib/Braintree/Test/CreditCardNumbers.php +69 -0
- lib/Braintree/Test/MerchantAccount.php +19 -0
- lib/Braintree/Test/Nonces.php +31 -0
- lib/Braintree/Test/TransactionAmounts.php +17 -0
- lib/Braintree/Test/VenmoSdk.php +28 -0
- lib/Braintree/TextNode.php +10 -0
- lib/Braintree/Transaction.php +504 -0
- lib/Braintree/Transaction/AddressDetails.php +24 -0
- lib/Braintree/Transaction/ApplePayCardDetails.php +36 -0
- lib/Braintree/Transaction/CoinbaseDetails.php +36 -0
- lib/Braintree/Transaction/CreditCardDetails.php +35 -0
- lib/Braintree/Transaction/CustomerDetails.php +22 -0
- lib/Braintree/Transaction/PayPalDetails.php +36 -0
- lib/Braintree/Transaction/StatusDetails.php +18 -0
- lib/Braintree/Transaction/SubscriptionDetails.php +15 -0
- lib/Braintree/TransactionGateway.php +444 -0
- lib/Braintree/TransactionSearch.php +131 -0
- lib/Braintree/TransparentRedirect.php +100 -0
- lib/Braintree/TransparentRedirectGateway.php +282 -0
- lib/Braintree/UnknownPaymentMethod.php +68 -0
- lib/Braintree/Util.php +332 -0
- lib/Braintree/Version.php +33 -0
- lib/Braintree/WebhookNotification.php +120 -0
- lib/Braintree/WebhookTesting.php +283 -0
- lib/Braintree/Xml.php +38 -0
- lib/Braintree/Xml/Generator.php +144 -0
- lib/Braintree/Xml/Parser.php +179 -0
- lib/ssl/api_braintreegateway_com.ca.crt +351 -0
- lib/ssl/sandbox_braintreegateway_com.ca.crt +20 -0
- package.xml +18 -0
- skin/frontend/base/default/images/gene/braintree/.DS_Store +0 -0
- skin/frontend/base/default/images/gene/braintree/AE.png +0 -0
- skin/frontend/base/default/images/gene/braintree/DI.png +0 -0
- skin/frontend/base/default/images/gene/braintree/JCB.png +0 -0
- skin/frontend/base/default/images/gene/braintree/MC.png +0 -0
- skin/frontend/base/default/images/gene/braintree/ME.png +0 -0
- skin/frontend/base/default/images/gene/braintree/PP.png +0 -0
- skin/frontend/base/default/images/gene/braintree/VI.png +0 -0
- skin/frontend/base/default/images/gene/braintree/card.png +0 -0
app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_Report_Transactions
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_Report_Transactions extends Mage_Adminhtml_Block_Widget_Grid_Container
|
9 |
+
{
|
10 |
+
public function __construct()
|
11 |
+
{
|
12 |
+
$this->_blockGroup = 'gene_braintree';
|
13 |
+
$this->_controller = 'adminhtml_report_transactions';
|
14 |
+
$this->_headerText = Mage::helper('gene_braintree')->__('Braintree Transactions');
|
15 |
+
|
16 |
+
parent::__construct();
|
17 |
+
|
18 |
+
$this->_removeButton('add');
|
19 |
+
}
|
20 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions/Grid.php
ADDED
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_Report_Transactions_Grid
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_Report_Transactions_Grid extends Mage_Adminhtml_Block_Widget_Grid
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* We allow overriding of the search query
|
12 |
+
*/
|
13 |
+
private $searchQuery = false;
|
14 |
+
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
parent::__construct();
|
18 |
+
$this->setId('gene_braintree_settlement_grid');
|
19 |
+
$this->setDefaultSort('qty_ordered');
|
20 |
+
$this->setDefaultDir('DESC');
|
21 |
+
|
22 |
+
// As we're building a custom collection the standard filters won't work
|
23 |
+
$this->setPagerVisibility(false);
|
24 |
+
$this->setFilterVisibility(false);
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Allow anyone invoking this grid to overriding the search query
|
29 |
+
*
|
30 |
+
* @param $query
|
31 |
+
*/
|
32 |
+
public function setSearchQuery($query)
|
33 |
+
{
|
34 |
+
$this->searchQuery = $query;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Build up a search query based on the users entries
|
39 |
+
*
|
40 |
+
* @return $this
|
41 |
+
*/
|
42 |
+
protected function _prepareBraintreeSearchQuery()
|
43 |
+
{
|
44 |
+
// Has the search query been set already?
|
45 |
+
if($this->searchQuery) {
|
46 |
+
return $this->searchQuery;
|
47 |
+
}
|
48 |
+
|
49 |
+
$searchArray = array();
|
50 |
+
|
51 |
+
// Init some times
|
52 |
+
$to = new Datetime();
|
53 |
+
$from = clone $to;
|
54 |
+
$from = $from->modify("-24 hour");
|
55 |
+
|
56 |
+
// If a from and to date are set modify things
|
57 |
+
if(Mage::app()->getRequest()->getParam('from_date') && Mage::app()->getRequest()->getParam('to_date')) {
|
58 |
+
$from = new DateTime(Mage::app()->getRequest()->getParam('from_date'));
|
59 |
+
$to = new DateTime(Mage::app()->getRequest()->getParam('to_date'));
|
60 |
+
}
|
61 |
+
|
62 |
+
// We always want to be filtering by a date to some degree
|
63 |
+
$searchArray[] = Braintree_TransactionSearch::createdAt()->between($from, $to);
|
64 |
+
|
65 |
+
// Type search
|
66 |
+
if($type = Mage::app()->getRequest()->getParam('type')) {
|
67 |
+
$searchArray[] = Braintree_TransactionSearch::type()->is($type);
|
68 |
+
}
|
69 |
+
|
70 |
+
// Allow searching upon the status
|
71 |
+
if($status = Mage::app()->getRequest()->getParam('status')) {
|
72 |
+
$searchArray[] = Braintree_TransactionSearch::status()->is($status);
|
73 |
+
}
|
74 |
+
|
75 |
+
// Order ID searching can be helpful
|
76 |
+
if($orderId = Mage::app()->getRequest()->getParam('order_id')) {
|
77 |
+
$searchArray[] = Braintree_TransactionSearch::orderId()->is($orderId);
|
78 |
+
}
|
79 |
+
|
80 |
+
// Store the search query within the session
|
81 |
+
Mage::getSingleton('adminhtml/session')->setBraintreeSearchQuery($searchArray);
|
82 |
+
|
83 |
+
return $searchArray;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Prepare the collection for the report
|
88 |
+
*
|
89 |
+
* @return $this|Mage_Adminhtml_Block_Widget_Grid
|
90 |
+
*/
|
91 |
+
protected function _prepareCollection()
|
92 |
+
{
|
93 |
+
// Add in a new collection
|
94 |
+
$collection = new Varien_Data_Collection();
|
95 |
+
|
96 |
+
// Init the wrapper
|
97 |
+
$wrapper = Mage::getModel('gene_braintree/wrapper_braintree');
|
98 |
+
|
99 |
+
// Validate the credentials
|
100 |
+
if($wrapper->validateCredentials()) {
|
101 |
+
|
102 |
+
// Grab all transactions
|
103 |
+
$transactions = Braintree_Transaction::search($this->_prepareBraintreeSearchQuery());
|
104 |
+
|
105 |
+
// Retrieve the order IDs
|
106 |
+
$orderIds = array();
|
107 |
+
/* @var $transaction Braintree_Transaction */
|
108 |
+
foreach ($transactions as $transaction) {
|
109 |
+
$orderIds[] = $transaction->orderId;
|
110 |
+
}
|
111 |
+
|
112 |
+
// Retrieve all of the orders from a collection
|
113 |
+
$orders = Mage::getResourceModel('sales/order_collection')->addAttributeToFilter('increment_id', array('in' => $orderIds));
|
114 |
+
|
115 |
+
/* @var $transaction Braintree_Transaction */
|
116 |
+
foreach ($transactions as $transaction) {
|
117 |
+
|
118 |
+
// Create a new varien object
|
119 |
+
$transactionItem = new Varien_Object();
|
120 |
+
$transactionItem->setData((array)$transaction->_attributes);
|
121 |
+
|
122 |
+
// Grab the Magento order from the previously built collection
|
123 |
+
/* @var $magentoOrder Mage_Sales_Model_Order */
|
124 |
+
$magentoOrder = $orders->getItemByColumnValue('increment_id', $transaction->orderId);
|
125 |
+
|
126 |
+
// Set the Magento Order ID into the collection
|
127 |
+
// Not all transactions maybe coming from Magento
|
128 |
+
if ($magentoOrder && $magentoOrder->getId()) {
|
129 |
+
$transactionItem->setMagentoOrderId($magentoOrder->getId());
|
130 |
+
$transactionItem->setOrderStatus($magentoOrder->getStatus());
|
131 |
+
} else {
|
132 |
+
$transactionItem->setOrderStatus('<em>Unknown</em>');
|
133 |
+
}
|
134 |
+
|
135 |
+
// Add the item into the collection
|
136 |
+
$collection->addItem($transactionItem);
|
137 |
+
}
|
138 |
+
|
139 |
+
} else {
|
140 |
+
|
141 |
+
// If the Braintree details aren't valid take them to the configuration page
|
142 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('gene_braintree')->__('You must enter valid details into the Braintree v.zero - Configuration payment method before viewing transactions.'));
|
143 |
+
|
144 |
+
// Send the users on their way
|
145 |
+
Mage::app()->getResponse()->setRedirect(Mage::helper('adminhtml')->getUrl('/system_config/edit/section/payment') . '#payment_gene_braintree-head');
|
146 |
+
Mage::app()->getResponse()->sendResponse();
|
147 |
+
|
148 |
+
// Stop processing this method
|
149 |
+
return false;
|
150 |
+
}
|
151 |
+
|
152 |
+
$this->setCollection($collection);
|
153 |
+
parent::_prepareCollection();
|
154 |
+
return $this;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Prepare the columns we're wanting to display
|
159 |
+
*
|
160 |
+
* @return $this
|
161 |
+
*
|
162 |
+
* @throws Exception
|
163 |
+
*/
|
164 |
+
protected function _prepareColumns()
|
165 |
+
{
|
166 |
+
$helper = Mage::helper('gene_braintree');
|
167 |
+
|
168 |
+
$this->addColumn('id', array(
|
169 |
+
'header' => $helper->__('ID'),
|
170 |
+
'index' => 'id',
|
171 |
+
'width' => 120,
|
172 |
+
'filter' => false,
|
173 |
+
'sortable' => false
|
174 |
+
));
|
175 |
+
|
176 |
+
$this->addColumn('created_at', array(
|
177 |
+
'header' => $helper->__('Transaction Date'),
|
178 |
+
'index' => 'created_at',
|
179 |
+
'type' => 'datetime',
|
180 |
+
'frame_callback' => array($this, 'handleDate'),
|
181 |
+
'filter' => false,
|
182 |
+
'sortable' => false
|
183 |
+
));
|
184 |
+
|
185 |
+
$this->addColumn('orderId', array(
|
186 |
+
'header' => $helper->__('Magento Order ID'),
|
187 |
+
'index' => 'orderId',
|
188 |
+
'width' => 120,
|
189 |
+
'filter' => false,
|
190 |
+
'sortable' => false
|
191 |
+
));
|
192 |
+
|
193 |
+
$this->addColumn('order_status', array(
|
194 |
+
'header' => $helper->__('Magento Status'),
|
195 |
+
'index' => 'order_status',
|
196 |
+
'type' => 'options',
|
197 |
+
'options' => Mage::getSingleton('sales/order_config')->getStatuses(),
|
198 |
+
'filter' => false,
|
199 |
+
'sortable' => false
|
200 |
+
));
|
201 |
+
|
202 |
+
$this->addColumn('merchantAccountId', array(
|
203 |
+
'header' => $helper->__('Merchant Account ID'),
|
204 |
+
'index' => 'merchantAccountId',
|
205 |
+
'filter' => false,
|
206 |
+
'sortable' => false
|
207 |
+
));
|
208 |
+
|
209 |
+
$this->addColumn('type', array(
|
210 |
+
'header' => $helper->__('Type'),
|
211 |
+
'index' => 'type',
|
212 |
+
'frame_callback' => array($this, 'handleType'),
|
213 |
+
'filter' => false,
|
214 |
+
'sortable' => false
|
215 |
+
));
|
216 |
+
|
217 |
+
$this->addColumn('payment_information', array(
|
218 |
+
'header' => $helper->__('Payment Information'),
|
219 |
+
'index' => 'payment_information',
|
220 |
+
'frame_callback' => array($this, 'handlePaymentInformation'),
|
221 |
+
'filter' => false,
|
222 |
+
'sortable' => false
|
223 |
+
));
|
224 |
+
|
225 |
+
$this->addColumn('amount', array(
|
226 |
+
'header' => $helper->__('Amount'),
|
227 |
+
'index' => 'amount',
|
228 |
+
'type' => 'number',
|
229 |
+
'frame_callback' => array($this, 'handleAmount'),
|
230 |
+
'filter' => false,
|
231 |
+
'sortable' => false
|
232 |
+
));
|
233 |
+
|
234 |
+
$this->addColumn('currencyIsoCode', array(
|
235 |
+
'header' => $helper->__('Currency'),
|
236 |
+
'index' => 'currencyIsoCode',
|
237 |
+
'filter' => false,
|
238 |
+
'sortable' => false
|
239 |
+
));
|
240 |
+
|
241 |
+
$this->addColumn('status', array(
|
242 |
+
'header' => $helper->__('Braintree Status'),
|
243 |
+
'type' => 'options',
|
244 |
+
'options' => $helper->getStatusesAsArray(),
|
245 |
+
'index' => 'status',
|
246 |
+
'filter' => false,
|
247 |
+
'sortable' => false
|
248 |
+
));
|
249 |
+
|
250 |
+
// Allow the admin to export this viewed data
|
251 |
+
$this->addExportType('*/*/exportCsv', $helper->__('CSV'));
|
252 |
+
$this->addExportType('*/*/exportExcel', $helper->__('Excel XML'));
|
253 |
+
|
254 |
+
return parent::_prepareColumns();
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Format the amount into the currency of the transaction
|
259 |
+
*
|
260 |
+
* @param $value
|
261 |
+
* @param $row
|
262 |
+
* @param $column
|
263 |
+
* @param $isExport
|
264 |
+
*
|
265 |
+
* @return string
|
266 |
+
* @throws Zend_Currency_Exception
|
267 |
+
*/
|
268 |
+
public function handleAmount($value, $row, $column, $isExport)
|
269 |
+
{
|
270 |
+
return Mage::app()->getLocale()->currency($row['currencyIsoCode'])->toCurrency($value);
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Return the date object as a timestamp
|
275 |
+
*
|
276 |
+
* @param $value
|
277 |
+
* @param $row
|
278 |
+
* @param $column
|
279 |
+
* @param $isExport
|
280 |
+
*
|
281 |
+
* @return int
|
282 |
+
*/
|
283 |
+
public function handleDate($value, $row, $column, $isExport)
|
284 |
+
{
|
285 |
+
/* @var $date DateTime */
|
286 |
+
$date = $row['createdAt'];
|
287 |
+
|
288 |
+
return $date->format('r');
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Upper case the first letter of the type
|
293 |
+
*
|
294 |
+
* @param $value
|
295 |
+
* @param $row
|
296 |
+
* @param $column
|
297 |
+
* @param $isExport
|
298 |
+
*
|
299 |
+
* @return string
|
300 |
+
*/
|
301 |
+
public function handleType($value, $row, $column, $isExport)
|
302 |
+
{
|
303 |
+
return ucfirst($value);
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Display payment information regarding the transaction
|
308 |
+
*
|
309 |
+
* @param $value
|
310 |
+
* @param $row
|
311 |
+
* @param $column
|
312 |
+
* @param $isExport
|
313 |
+
*
|
314 |
+
* @return string
|
315 |
+
*/
|
316 |
+
public function handlePaymentInformation($value, $row, $column, $isExport)
|
317 |
+
{
|
318 |
+
// Grab the image associated with this payment
|
319 |
+
$image = false;
|
320 |
+
if(!$isExport) {
|
321 |
+
$image = '<img height="26" align="left" src=' . (isset($row['paymentInstrumentType']) && $row['paymentInstrumentType'] == 'paypal_account' ? $row['paypal']['imageUrl'] : $row['creditCard']['imageUrl']) . '" /> ';
|
322 |
+
}
|
323 |
+
|
324 |
+
// Display the actual payment information
|
325 |
+
$response = false;
|
326 |
+
if(isset($row['paymentInstrumentType']) && $row['paymentInstrumentType'] == 'paypal_account') {
|
327 |
+
$response = $image . $row['paypal']['payerEmail'];
|
328 |
+
} else if(isset($row['paymentInstrumentType']) && $row['paymentInstrumentType'] == 'credit_card') {
|
329 |
+
$response = $image . $row['creditCard']['bin'] . '******' . $row['creditCard']['last4'];
|
330 |
+
}
|
331 |
+
|
332 |
+
return (!$isExport ? '<span style="line-height: 26px;">' : '') . $response . (!$isExport ? '</span>' : '');
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* If an item has a Magento Order ID take them to the sales order view screen
|
337 |
+
*
|
338 |
+
* @param $row
|
339 |
+
*
|
340 |
+
* @return string
|
341 |
+
*/
|
342 |
+
public function getRowUrl($row)
|
343 |
+
{
|
344 |
+
if($row->getMagentoOrderId()) {
|
345 |
+
return $this->getUrl('*/sales_order/view', array('order_id' => $row->getMagentoOrderId()));
|
346 |
+
}
|
347 |
+
return false;
|
348 |
+
}
|
349 |
+
|
350 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/Report/Transactions/Search.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_Report_Transactions_Search
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_Report_Transactions_Search extends Mage_Core_Block_Template
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Return the from date
|
12 |
+
*
|
13 |
+
* @return string
|
14 |
+
*/
|
15 |
+
public function getFromDate()
|
16 |
+
{
|
17 |
+
if($fromDate = Mage::app()->getRequest()->getParam('from_date')) {
|
18 |
+
return $fromDate;
|
19 |
+
}
|
20 |
+
|
21 |
+
return $this->formateDateBraintree(strtotime('-24 hour'));
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Return the to date
|
26 |
+
*
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
public function getToDate()
|
30 |
+
{
|
31 |
+
if($toDate = Mage::app()->getRequest()->getParam('to_date')) {
|
32 |
+
return $toDate;
|
33 |
+
}
|
34 |
+
|
35 |
+
return $this->formateDateBraintree(time());
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Return all of the possible statuses
|
40 |
+
*
|
41 |
+
* @return array
|
42 |
+
*/
|
43 |
+
public function getStatusesAsArray()
|
44 |
+
{
|
45 |
+
// Add in a show all option
|
46 |
+
$all[''] = 'Show All';
|
47 |
+
|
48 |
+
// Grab all the statuses
|
49 |
+
$statuses = Mage::helper('gene_braintree')->getStatusesAsArray();
|
50 |
+
|
51 |
+
// Combine them
|
52 |
+
return array_merge($all, $statuses);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Return the types as an array
|
57 |
+
*
|
58 |
+
* @return array
|
59 |
+
*/
|
60 |
+
public function getTypesAsArray()
|
61 |
+
{
|
62 |
+
return array(
|
63 |
+
'' => 'All',
|
64 |
+
'sale' => 'Sale',
|
65 |
+
'credit' => 'Credit'
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Return the selected status
|
71 |
+
*
|
72 |
+
* @return mixed
|
73 |
+
*/
|
74 |
+
public function getSelectedType()
|
75 |
+
{
|
76 |
+
return Mage::app()->getRequest()->getParam('type');
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Return the selected status
|
81 |
+
*
|
82 |
+
* @return mixed
|
83 |
+
*/
|
84 |
+
public function getSelectedStatus()
|
85 |
+
{
|
86 |
+
return Mage::app()->getRequest()->getParam('status');
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Return the selected status
|
91 |
+
*
|
92 |
+
* @return mixed
|
93 |
+
*/
|
94 |
+
public function getOrderId()
|
95 |
+
{
|
96 |
+
return Mage::app()->getRequest()->getParam('order_id');
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Format the date for display on the Braintree search form
|
101 |
+
*
|
102 |
+
* @param $date
|
103 |
+
*
|
104 |
+
* @return string
|
105 |
+
*/
|
106 |
+
public function formateDateBraintree($date)
|
107 |
+
{
|
108 |
+
return date('d-m-Y G:i', $date);
|
109 |
+
}
|
110 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Config.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Config
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Config
|
9 |
+
extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Render element html
|
13 |
+
*
|
14 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
18 |
+
{
|
19 |
+
$useContainerId = $element->getData('use_container_id');
|
20 |
+
return sprintf('<tr id="row_%s">
|
21 |
+
<td class="label">
|
22 |
+
<strong id="%s">%s</strong>
|
23 |
+
</td>
|
24 |
+
<td class="value">
|
25 |
+
%s
|
26 |
+
</td>
|
27 |
+
</tr>',
|
28 |
+
$element->getHtmlId(), $element->getHtmlId(), $element->getLabel(), $this->getValidConfigHtml()
|
29 |
+
);
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Inform the user there version will not work
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
+
private function getValidConfigHtml()
|
37 |
+
{
|
38 |
+
$response = Mage::getModel('gene_braintree/wrapper_braintree')->validateCredentials(true);
|
39 |
+
$response.= '
|
40 |
+
<script type="text/javascript">
|
41 |
+
|
42 |
+
// Set the config timeout
|
43 |
+
var configTimeout;
|
44 |
+
|
45 |
+
// Make a request to the server and validate the configuration options
|
46 |
+
function checkConfig() {
|
47 |
+
|
48 |
+
// Clear any timeout already set
|
49 |
+
clearTimeout(configTimeout);
|
50 |
+
|
51 |
+
// Defined the configTimeout
|
52 |
+
configTimeout = setTimeout(function() {
|
53 |
+
// Make the request
|
54 |
+
new Ajax.Request(
|
55 |
+
"' . Mage::helper('adminhtml')->getUrl('adminhtml/braintree/validateConfig') . '",
|
56 |
+
{
|
57 |
+
method: "post",
|
58 |
+
onSuccess: function(transport){
|
59 |
+
$(\'row_payment_gene_braintree_valid_config\').down(\'td.value\').innerHTML = transport.responseText;
|
60 |
+
},
|
61 |
+
parameters: Form.serializeElements($$(\'.validate-config\'))
|
62 |
+
}
|
63 |
+
);
|
64 |
+
}, 800);
|
65 |
+
}
|
66 |
+
|
67 |
+
// Observe the relevant form elements
|
68 |
+
$$(\'input.validate-config\').each(function(element) {
|
69 |
+
Event.observe(element, \'keyup\', function() {
|
70 |
+
checkConfig();
|
71 |
+
});
|
72 |
+
});
|
73 |
+
$$(\'select.validate-config\').each(function(element) {
|
74 |
+
Event.observe(element, \'change\', function() {
|
75 |
+
checkConfig();
|
76 |
+
});
|
77 |
+
});
|
78 |
+
</script>';
|
79 |
+
return $response;
|
80 |
+
}
|
81 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Currency.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Currency
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Currency
|
9 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Enter description here...
|
13 |
+
*
|
14 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
|
18 |
+
{
|
19 |
+
return $this->getCurrencyTableHtml($element);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Inform the user there version will not work
|
24 |
+
* @return string
|
25 |
+
*/
|
26 |
+
private function getCurrencyTableHtml(Varien_Data_Form_Element_Abstract $element)
|
27 |
+
{
|
28 |
+
// Store ID = scope ID
|
29 |
+
$storeId = Mage::getSingleton('adminhtml/config_data')->getScopeId();
|
30 |
+
|
31 |
+
// Retrieve the currencies
|
32 |
+
$currencies = Mage::app()->getStore($storeId)->getAvailableCurrencyCodes();
|
33 |
+
|
34 |
+
// Retrieve the values
|
35 |
+
$values = $element->getValue();
|
36 |
+
|
37 |
+
// Build our response
|
38 |
+
$response = '<input type="hidden" id="payment_gene_braintree_multi_currency_mapping" />
|
39 |
+
<table width="100%" cellspacing="6" cellpadding="4">
|
40 |
+
<tr>
|
41 |
+
<th width="35%">' . $this->__('Currency Code') . '</th>
|
42 |
+
<th width="65%">' . $this->__('Merchant Account ID') . '</th>
|
43 |
+
</tr>';
|
44 |
+
|
45 |
+
// Loop through each currency and add a value
|
46 |
+
foreach($currencies as $currency) {
|
47 |
+
$response .= '<tr>
|
48 |
+
<td> ' . $currency . '</td>
|
49 |
+
<td><input class="input-text" type="text" name=" ' . $element->getName() . '[' . $currency . ']" style="width: 100%;" value="'. (isset($values->$currency) ? $values->$currency : '') . '" /></td>
|
50 |
+
</tr>';
|
51 |
+
}
|
52 |
+
|
53 |
+
$response .= '</table>';
|
54 |
+
|
55 |
+
return $response;
|
56 |
+
}
|
57 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Moduleversion.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Moduleversion
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Moduleversion
|
9 |
+
extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Render element html
|
13 |
+
*
|
14 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
18 |
+
{
|
19 |
+
$useContainerId = $element->getData('use_container_id');
|
20 |
+
return sprintf('<tr id="row_%s">
|
21 |
+
<td class="label">
|
22 |
+
<strong id="%s">%s</strong>
|
23 |
+
</td>
|
24 |
+
<td class="value">
|
25 |
+
<span id="module-version">%s</span>
|
26 |
+
<div id="recent-version">
|
27 |
+
<div style="padding: 8px 0;line-height: 16px;">
|
28 |
+
<img src="' . $this->getSkinUrl('images/rule-ajax-loader.gif') . '" align="left" style="margin-right: 3px;" /> ' . $this->__('Checking latest version...') . '
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
</td>
|
32 |
+
</tr>',
|
33 |
+
$element->getHtmlId(), $element->getHtmlId(), $element->getLabel(), $this->getVersionHtml()
|
34 |
+
);
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Inform the user there version will not work
|
39 |
+
* @return string
|
40 |
+
*/
|
41 |
+
private function getVersionHtml()
|
42 |
+
{
|
43 |
+
$response = Mage::getConfig()->getModuleConfig('Gene_Braintree')->version;
|
44 |
+
$response.= '
|
45 |
+
<script type="text/javascript">
|
46 |
+
|
47 |
+
// Define the module version in the window
|
48 |
+
var moduleVersion = \'' . Mage::getConfig()->getModuleConfig('Gene_Braintree')->version . '\';
|
49 |
+
|
50 |
+
// Once the dom has loaded make the checkout
|
51 |
+
document.observe("dom:loaded", function() {
|
52 |
+
try {
|
53 |
+
new Ajax.Request("//braintree.gene.co.uk/", {
|
54 |
+
method: "post", parameters: {version: moduleVersion},
|
55 |
+
onCreate: function(response) {
|
56 |
+
var t = response.transport;
|
57 |
+
t.setRequestHeader = t.setRequestHeader.wrap(function(original, k, v) {
|
58 |
+
if (/^(accept|accept-language|content-language)$/i.test(k))
|
59 |
+
return original(k, v);
|
60 |
+
if (/^content-type$/i.test(k) &&
|
61 |
+
/^(application\/x-www-form-urlencoded|multipart\/form-data|text\/plain)(;.+)?$/i.test(v))
|
62 |
+
return original(k, v);
|
63 |
+
return;
|
64 |
+
});
|
65 |
+
},
|
66 |
+
onSuccess: function(transport) {
|
67 |
+
try {
|
68 |
+
json = eval(\'(\' + transport.responseText + \')\');
|
69 |
+
} catch(e){}
|
70 |
+
|
71 |
+
// Is there a message to be displayed to the user?
|
72 |
+
if(json.message) {
|
73 |
+
$(\'recent-version\').innerHTML = json.message;
|
74 |
+
}
|
75 |
+
|
76 |
+
if(json.latest == true) {
|
77 |
+
$(\'module-version\').setStyle({color: \'green\'});
|
78 |
+
} else {
|
79 |
+
$(\'module-version\').setStyle({color: \'darkred\'});
|
80 |
+
}
|
81 |
+
},
|
82 |
+
onFailure: function() {
|
83 |
+
$(\'recent-version\').innerHTML = \'<span style="color:darkred;">Unable to check for updates</span>\';
|
84 |
+
}
|
85 |
+
});
|
86 |
+
} catch(e) {
|
87 |
+
$(\'recent-version\').innerHTML = \'<span style="color:darkred;">Unable to check for updates</span>\';
|
88 |
+
}
|
89 |
+
});
|
90 |
+
</script>
|
91 |
+
';
|
92 |
+
|
93 |
+
return $response;
|
94 |
+
}
|
95 |
+
}
|
app/code/community/Gene/Braintree/Block/Adminhtml/System/Config/Braintree/Version.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Version
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Adminhtml_System_Config_Braintree_Version
|
9 |
+
extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Render element html
|
13 |
+
*
|
14 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
18 |
+
{
|
19 |
+
$useContainerId = $element->getData('use_container_id');
|
20 |
+
return sprintf('<tr id="row_%s">
|
21 |
+
<td class="label">
|
22 |
+
<strong id="%s">%s</strong>
|
23 |
+
</td>
|
24 |
+
<td class="value">
|
25 |
+
%s
|
26 |
+
</td>
|
27 |
+
</tr>',
|
28 |
+
$element->getHtmlId(), $element->getHtmlId(), $element->getLabel(), $this->getVersionHtml()
|
29 |
+
);
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Inform the user there version will not work
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
+
private function getVersionHtml()
|
37 |
+
{
|
38 |
+
if(@class_exists('Braintree_Version')) {
|
39 |
+
$version = Braintree_Version::get();
|
40 |
+
if ($version < 2.32) {
|
41 |
+
return '
|
42 |
+
<span style="color: red;">' . $version . '</span><br />
|
43 |
+
<small>
|
44 |
+
<strong>Warning:</strong> Our payment methods will not work with a version of the Braintree lib files older than 2.32.0. You\'ll have to upgrade, please download the newer version <a href="https://developers.braintreepayments.com/javascript+php/sdk/server/setup">here</a>. Once you\'ve downloaded it please replace the file <strong>/lib/Braintree.php</strong> and the folder <strong>/lib/Braintree/</strong> with the newer versions within the archive.
|
45 |
+
</small>';
|
46 |
+
} else {
|
47 |
+
return '<span style="color: green;">' . $version . '</span>';
|
48 |
+
}
|
49 |
+
} else {
|
50 |
+
return '<span style="color: red;font-weight: bold;">Not Installed</span>';
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
app/code/community/Gene/Braintree/Block/Cart/Totals.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Cart_Totals
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Cart_Totals extends Mage_Checkout_Block_Cart_Totals
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Check if we have display grand total in base currency
|
13 |
+
*
|
14 |
+
* @return bool
|
15 |
+
*/
|
16 |
+
public function needDisplayBaseGrandtotal()
|
17 |
+
{
|
18 |
+
// If we have a mapped currency code never display base grand total
|
19 |
+
if(Mage::getSingleton('gene_braintree/wrapper_braintree')->hasMappedCurrencyCode()) {
|
20 |
+
return false;
|
21 |
+
}
|
22 |
+
|
23 |
+
return parent::needDisplayBaseGrandtotal();
|
24 |
+
}
|
25 |
+
}
|
app/code/community/Gene/Braintree/Block/Creditcard.php
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Creditcard
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Creditcard extends Mage_Payment_Block_Form_Cc
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Store our saved details
|
12 |
+
*/
|
13 |
+
private $_savedDetails = false;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Set the template
|
17 |
+
*/
|
18 |
+
protected function _construct()
|
19 |
+
{
|
20 |
+
parent::_construct();
|
21 |
+
$this->setTemplate('gene/braintree/creditcard.phtml');
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Can we save the card?
|
26 |
+
*
|
27 |
+
* @return bool
|
28 |
+
*/
|
29 |
+
protected function canSaveCard()
|
30 |
+
{
|
31 |
+
// Validate that the vault is enabled and that the user is either logged in or registering
|
32 |
+
if ($this->getMethod()->isVaultEnabled()
|
33 |
+
&& (Mage::getSingleton('customer/session')->isLoggedIn()
|
34 |
+
|| Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER))
|
35 |
+
{
|
36 |
+
return true;
|
37 |
+
}
|
38 |
+
|
39 |
+
return false;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* is 3D secure enabled?
|
44 |
+
*
|
45 |
+
* @return mixed
|
46 |
+
*/
|
47 |
+
protected function is3DEnabled()
|
48 |
+
{
|
49 |
+
return Mage::getModel('gene_braintree/paymentmethod_creditcard')->is3DEnabled();
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Does this customer have saved accounts?
|
54 |
+
*
|
55 |
+
* @return mixed
|
56 |
+
*/
|
57 |
+
public function hasSavedDetails()
|
58 |
+
{
|
59 |
+
if(Mage::getSingleton('customer/session')->isLoggedIn()) {
|
60 |
+
if ($this->getSavedDetails()) {
|
61 |
+
return sizeof($this->getSavedDetails());
|
62 |
+
}
|
63 |
+
}
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Return the saved accounts
|
69 |
+
*
|
70 |
+
* @return array
|
71 |
+
*/
|
72 |
+
public function getSavedDetails()
|
73 |
+
{
|
74 |
+
if(!$this->_savedDetails) {
|
75 |
+
$this->_savedDetails = Mage::getSingleton('gene_braintree/saved')->getSavedMethodsByType(Gene_Braintree_Model_Saved::SAVED_CREDITCARD_ID);
|
76 |
+
}
|
77 |
+
return $this->_savedDetails;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Return the original CC types
|
82 |
+
*
|
83 |
+
* @return array
|
84 |
+
*/
|
85 |
+
public function getOriginalCcAvailableTypes()
|
86 |
+
{
|
87 |
+
return parent::getCcAvailableTypes();
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Convert the available types into something
|
92 |
+
*
|
93 |
+
* @return string
|
94 |
+
*/
|
95 |
+
public function getCcAvailableTypes()
|
96 |
+
{
|
97 |
+
// Collect the types from the core method
|
98 |
+
$types = parent::getCcAvailableTypes();
|
99 |
+
|
100 |
+
// Grab the keys and encode
|
101 |
+
return json_encode(array_keys($types));
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Return the card icon
|
106 |
+
*
|
107 |
+
* @param $cardType
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
static public function getCardIcon($cardType)
|
112 |
+
{
|
113 |
+
// Convert the card type to lower case, no spaces
|
114 |
+
switch(str_replace(' ', '', strtolower($cardType))) {
|
115 |
+
case 'mastercard':
|
116 |
+
return 'MC.png';
|
117 |
+
break;
|
118 |
+
case 'visa':
|
119 |
+
return 'VI.png';
|
120 |
+
break;
|
121 |
+
case 'americanexpress':
|
122 |
+
case 'amex':
|
123 |
+
return 'AE.png';
|
124 |
+
break;
|
125 |
+
case 'discover':
|
126 |
+
return 'DI.png';
|
127 |
+
break;
|
128 |
+
case 'jcb':
|
129 |
+
return 'JCB.png';
|
130 |
+
break;
|
131 |
+
case 'maestro':
|
132 |
+
return 'ME.png';
|
133 |
+
break;
|
134 |
+
case 'paypal':
|
135 |
+
return 'PP.png';
|
136 |
+
break;
|
137 |
+
}
|
138 |
+
|
139 |
+
// Otherwise return the standard card image
|
140 |
+
return 'card.png';
|
141 |
+
}
|
142 |
+
|
143 |
+
}
|
app/code/community/Gene/Braintree/Block/Creditcard/Info.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Creditcard_Info
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Creditcard_Info extends Mage_Payment_Block_Info
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Use a custom template
|
13 |
+
*/
|
14 |
+
protected function _construct()
|
15 |
+
{
|
16 |
+
parent::_construct();
|
17 |
+
$this->setTemplate('gene/braintree/creditcard/info.phtml');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Return the currently viewed order
|
22 |
+
*
|
23 |
+
* @return \Mage_Sales_Model_Order
|
24 |
+
*/
|
25 |
+
protected function getOrder()
|
26 |
+
{
|
27 |
+
if(Mage::registry('current_order')) {
|
28 |
+
return Mage::registry('current_order');
|
29 |
+
} else if(Mage::registry('current_invoice')) {
|
30 |
+
return Mage::registry('current_invoice')->getOrder();
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Prepare information specific to current payment method
|
36 |
+
*
|
37 |
+
* @param null | array $transport
|
38 |
+
*
|
39 |
+
* @return Varien_Object
|
40 |
+
*/
|
41 |
+
protected function _prepareSpecificInformation($transport = null)
|
42 |
+
{
|
43 |
+
// Get the original transport data
|
44 |
+
$transport = parent::_prepareSpecificInformation($transport);
|
45 |
+
|
46 |
+
// Build up the data we wish to pass through
|
47 |
+
$data = array(
|
48 |
+
$this->__('Card Number (Last 4)') => $this->getInfo()->getCcLast4(),
|
49 |
+
$this->__('Credit Card Type') => $this->getInfo()->getCcType()
|
50 |
+
);
|
51 |
+
|
52 |
+
// Check we're in the admin area
|
53 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
54 |
+
|
55 |
+
// Transaction ID won't matter for customers
|
56 |
+
$data[$this->__('Braintree Transaction ID')] = $this->getInfo()->getLastTransId();
|
57 |
+
|
58 |
+
// Add in the current status
|
59 |
+
try {
|
60 |
+
$transaction = Mage::getModel('gene_braintree/wrapper_braintree')->init($this->getOrder()->getStoreId())->findTransaction($this->getInfo()->getLastTransId());
|
61 |
+
if ($transaction) {
|
62 |
+
$data[$this->__('Status')] = $this->convertStatus($transaction->status);
|
63 |
+
} else {
|
64 |
+
$data[$this->__('Status')] = $this->__('<span style="color:red;"><strong>Warning:</strong> Cannot load payment in Braintree.</span>');
|
65 |
+
}
|
66 |
+
} catch (Exception $e) {
|
67 |
+
$data[$this->__('Status')] = $this->__('<span style="color:red;"><strong>Warning:</strong> Unable to connect to Braintree to load transaction.</span>');
|
68 |
+
}
|
69 |
+
|
70 |
+
// What additional information should we show
|
71 |
+
$additionalInfoHeadings = array(
|
72 |
+
'avsErrorResponseCode' => $this->__('AVS Error Response Code'),
|
73 |
+
'avsPostalCodeResponseCode' => $this->__('AVS Postal Response Code'),
|
74 |
+
'avsStreetAddressResponseCode' => $this->__('AVS Street Address Response Code'),
|
75 |
+
'cvvResponseCode' => $this->__('CVV Response Code'),
|
76 |
+
'gatewayRejectionReason' => $this->__('Gateway Rejection Reason'),
|
77 |
+
'processorAuthorizationCode' => $this->__('Processor Autorization Code'),
|
78 |
+
'processorResponseCode' => $this->__('Processor Response Code'),
|
79 |
+
'processorResponseText' => $this->__('Processor Response Text'),
|
80 |
+
'threeDSecure' => $this->__('3D Secure')
|
81 |
+
);
|
82 |
+
|
83 |
+
// Add any of the data that we've recorded into the view
|
84 |
+
foreach($additionalInfoHeadings as $key => $heading) {
|
85 |
+
if($infoData = $this->getInfo()->getAdditionalInformation($key)) {
|
86 |
+
$data[$heading] = $infoData;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
91 |
+
|
92 |
+
// Add the data to the class variable
|
93 |
+
$transport->setData(array_merge($data, $transport->getData()));
|
94 |
+
$this->_paymentSpecificInformation = $transport->getData();
|
95 |
+
|
96 |
+
// And return it
|
97 |
+
return $transport;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Make the status nicer to read
|
102 |
+
*
|
103 |
+
* @param $status
|
104 |
+
*
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
private function convertStatus($status)
|
108 |
+
{
|
109 |
+
switch($status){
|
110 |
+
case 'authorized':
|
111 |
+
return '<span style="color: #40A500;"> ' . Mage::helper('gene_braintree')->__('Authorized') . '</span>';
|
112 |
+
break;
|
113 |
+
case 'submitted_for_settlement':
|
114 |
+
return '<span style="color: #40A500;">' . Mage::helper('gene_braintree')->__('Submitted For Settlement') . '</span>';
|
115 |
+
break;
|
116 |
+
case 'settled':
|
117 |
+
return '<span style="color: #40A500;">' . Mage::helper('gene_braintree')->__('Settled') . '</span>';
|
118 |
+
break;
|
119 |
+
case 'voided':
|
120 |
+
return '<span style="color: #ed4737;">' . Mage::helper('gene_braintree')->__('Voided') . '</span>';
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
|
124 |
+
return ucwords($status);
|
125 |
+
}
|
126 |
+
|
127 |
+
}
|
app/code/community/Gene/Braintree/Block/Creditcard/Threedsecure.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Creditcard_Threedsecure
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Creditcard_Threedsecure extends Mage_Core_Block_Template
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Only render if the payment method is active and 3D secure is enabled
|
12 |
+
*
|
13 |
+
* @return string
|
14 |
+
*/
|
15 |
+
protected function _toHtml()
|
16 |
+
{
|
17 |
+
// Check the payment method is active
|
18 |
+
if (Mage::getModel('gene_braintree/paymentmethod_creditcard')->isAvailable()
|
19 |
+
&& Mage::getModel('gene_braintree/paymentmethod_creditcard')->is3DEnabled()
|
20 |
+
) {
|
21 |
+
return parent::_toHtml();
|
22 |
+
}
|
23 |
+
|
24 |
+
return '';
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Gene/Braintree/Block/Js.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Js
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Js extends Mage_Core_Block_Template
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* We can use the same token twice
|
12 |
+
* @var bool
|
13 |
+
*/
|
14 |
+
private $token = false;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Log whether methods are active
|
18 |
+
*
|
19 |
+
* @var bool
|
20 |
+
*/
|
21 |
+
private $creditCardActive = null;
|
22 |
+
private $payPalActive = null;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Return whether PayPal is active
|
26 |
+
*
|
27 |
+
* @return bool|null
|
28 |
+
*/
|
29 |
+
protected function isCreditCardActive()
|
30 |
+
{
|
31 |
+
if(is_null($this->creditCardActive)) {
|
32 |
+
$this->creditCardActive = Mage::getModel('gene_braintree/paymentmethod_creditcard')->isAvailable();
|
33 |
+
}
|
34 |
+
|
35 |
+
return $this->creditCardActive;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Return whether PayPal is active
|
40 |
+
*
|
41 |
+
* @return bool|null
|
42 |
+
*/
|
43 |
+
protected function isPayPalActive()
|
44 |
+
{
|
45 |
+
if(is_null($this->payPalActive)) {
|
46 |
+
$this->payPalActive = Mage::getModel('gene_braintree/paymentmethod_paypal')->isAvailable();
|
47 |
+
}
|
48 |
+
|
49 |
+
return $this->payPalActive;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* is 3D secure enabled?
|
54 |
+
*
|
55 |
+
* @return int
|
56 |
+
*/
|
57 |
+
protected function is3DEnabled()
|
58 |
+
{
|
59 |
+
// Return an int
|
60 |
+
if(Mage::getModel('gene_braintree/paymentmethod_creditcard')->is3DEnabled()) {
|
61 |
+
return 1;
|
62 |
+
} else {
|
63 |
+
return 0;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Generate and return a token
|
69 |
+
*
|
70 |
+
* @return mixed
|
71 |
+
*/
|
72 |
+
protected function getClientToken()
|
73 |
+
{
|
74 |
+
if(!$this->token) {
|
75 |
+
$this->token = Mage::getSingleton('gene_braintree/wrapper_braintree')->init()->generateToken();
|
76 |
+
}
|
77 |
+
return $this->token;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Shall we do a single use payment?
|
82 |
+
*
|
83 |
+
* @return string
|
84 |
+
*/
|
85 |
+
protected function getSingleUse()
|
86 |
+
{
|
87 |
+
// We prefer to do future payments, so anything else is future
|
88 |
+
$paymentAction = Mage::getStoreConfig('payment/gene_braintree_paypal/payment_type');
|
89 |
+
if($paymentAction == Gene_Braintree_Model_Source_Paypal_Paymenttype::GENE_BRAINTREE_PAYPAL_SINGLE_PAYMENT) {
|
90 |
+
return 'true';
|
91 |
+
}
|
92 |
+
|
93 |
+
return 'false';
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* If we're using future payments should we retrieve a token or just do a singular payment?
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
protected function getSingleFutureUse()
|
102 |
+
{
|
103 |
+
// We prefer to do future payments, so anything else is future
|
104 |
+
$paymentAction = Mage::getStoreConfig('payment/gene_braintree_paypal/payment_type');
|
105 |
+
if($paymentAction == Gene_Braintree_Model_Source_Paypal_Paymenttype::GENE_BRAINTREE_PAYPAL_FUTURE_PAYMENTS
|
106 |
+
&& !Mage::getModel('gene_braintree/paymentmethod_paypal')->isVaultEnabled()) {
|
107 |
+
return 'true';
|
108 |
+
}
|
109 |
+
|
110 |
+
return 'false';
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Return the locale for PayPal
|
115 |
+
*
|
116 |
+
* @return mixed
|
117 |
+
*/
|
118 |
+
protected function getLocale()
|
119 |
+
{
|
120 |
+
return Mage::getStoreConfig('payment/gene_braintree_paypal/locale');
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Only render if the payment method is active
|
125 |
+
*
|
126 |
+
* @return string
|
127 |
+
*/
|
128 |
+
protected function _toHtml()
|
129 |
+
{
|
130 |
+
// Check the payment method is active
|
131 |
+
if($this->isCreditCardActive() || $this->isPayPalActive()) {
|
132 |
+
return parent::_toHtml();
|
133 |
+
}
|
134 |
+
|
135 |
+
return '';
|
136 |
+
}
|
137 |
+
|
138 |
+
}
|
app/code/community/Gene/Braintree/Block/Paypal.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Form
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Paypal extends Mage_Payment_Block_Form
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Store this so we don't load it multiple times
|
13 |
+
*/
|
14 |
+
private $_savedDetails = false;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Internal constructor. Set template
|
18 |
+
*/
|
19 |
+
protected function _construct()
|
20 |
+
{
|
21 |
+
parent::_construct();
|
22 |
+
$this->setTemplate('gene/braintree/paypal.phtml');
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Generate and return a token
|
27 |
+
*
|
28 |
+
* @return mixed
|
29 |
+
*/
|
30 |
+
public function getClientToken()
|
31 |
+
{
|
32 |
+
return Mage::getModel('gene_braintree/wrapper_braintree')->init()->generateToken();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Shall we do a single use payment?
|
37 |
+
*
|
38 |
+
* @return string
|
39 |
+
*/
|
40 |
+
public function getSingleUse()
|
41 |
+
{
|
42 |
+
// We prefer to do future payments, so anything else is future
|
43 |
+
$paymentAction = Mage::getStoreConfig('payment/gene_braintree_paypal/payment_type');
|
44 |
+
if($paymentAction == Gene_Braintree_Model_Source_Paypal_Paymenttype::GENE_BRAINTREE_PAYPAL_SINGLE_PAYMENT) {
|
45 |
+
return 'true';
|
46 |
+
}
|
47 |
+
|
48 |
+
return 'false';
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Does this customer have saved accounts?
|
53 |
+
*
|
54 |
+
* @return mixed
|
55 |
+
*/
|
56 |
+
public function hasSavedDetails()
|
57 |
+
{
|
58 |
+
if(Mage::getSingleton('customer/session')->isLoggedIn()) {
|
59 |
+
if($this->getSavedDetails()) {
|
60 |
+
return sizeof($this->getSavedDetails());
|
61 |
+
}
|
62 |
+
}
|
63 |
+
return false;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Return the saved accounts
|
68 |
+
*
|
69 |
+
* @return bool
|
70 |
+
*/
|
71 |
+
public function getSavedDetails()
|
72 |
+
{
|
73 |
+
if(!$this->_savedDetails) {
|
74 |
+
$this->_savedDetails = Mage::getSingleton('gene_braintree/saved')->getSavedMethodsByType(Gene_Braintree_Model_Saved::SAVED_PAYPAL_ID);
|
75 |
+
}
|
76 |
+
return $this->_savedDetails;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Is the vault enabled? Meaning we can save PayPal
|
81 |
+
*
|
82 |
+
* @return mixed
|
83 |
+
*/
|
84 |
+
public function canSavePayPal()
|
85 |
+
{
|
86 |
+
if ($this->getMethod()->isVaultEnabled()
|
87 |
+
&& (Mage::getSingleton('customer/session')->isLoggedIn()
|
88 |
+
|| Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER))
|
89 |
+
{
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
|
96 |
+
}
|
app/code/community/Gene/Braintree/Block/Paypal/Info.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Info
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Paypal_Info extends Mage_Payment_Block_Info
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Use a custom template
|
13 |
+
*/
|
14 |
+
protected function _construct()
|
15 |
+
{
|
16 |
+
parent::_construct();
|
17 |
+
$this->setTemplate('gene/braintree/paypal/info.phtml');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Prepare information specific to current payment method
|
22 |
+
*
|
23 |
+
* @param null | array $transport
|
24 |
+
*
|
25 |
+
* @return Varien_Object
|
26 |
+
*/
|
27 |
+
protected function _prepareSpecificInformation($transport = null)
|
28 |
+
{
|
29 |
+
// Get the original transport data
|
30 |
+
$transport = parent::_prepareSpecificInformation($transport);
|
31 |
+
|
32 |
+
// Build up the data we wish to pass through
|
33 |
+
$data = array(
|
34 |
+
$this->__('PayPal Email') => $this->getInfo()->getAdditionalInformation('paypal_email')
|
35 |
+
);
|
36 |
+
|
37 |
+
// Check we're in the admin area
|
38 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
39 |
+
|
40 |
+
// Show these details to the admin only
|
41 |
+
$data = array_merge(
|
42 |
+
$data, array(
|
43 |
+
$this->__('Braintree Transaction ID') => $this->getInfo()->getLastTransId(),
|
44 |
+
$this->__('Payment ID') => $this->getInfo()->getAdditionalInformation('payment_id'),
|
45 |
+
$this->__('Authorization ID') => $this->getInfo()->getAdditionalInformation(
|
46 |
+
'authorization_id'
|
47 |
+
)
|
48 |
+
)
|
49 |
+
);
|
50 |
+
|
51 |
+
}
|
52 |
+
|
53 |
+
// Add the data to the class variable
|
54 |
+
$transport->setData(array_merge($data, $transport->getData()));
|
55 |
+
$this->_paymentSpecificInformation = $transport->getData();
|
56 |
+
|
57 |
+
// And return it
|
58 |
+
return $transport;
|
59 |
+
}
|
60 |
+
|
61 |
+
}
|
app/code/community/Gene/Braintree/Block/Saved.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Block_Saved
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Block_Saved extends Mage_Core_Block_Template
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Return whether the customer has saved details
|
12 |
+
*
|
13 |
+
* @param bool $type
|
14 |
+
*
|
15 |
+
* @return bool
|
16 |
+
*/
|
17 |
+
public function hasSavedDetails($type = false)
|
18 |
+
{
|
19 |
+
return Mage::getSingleton('gene_braintree/saved')->hasType($type);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Retrieve those said saved details
|
24 |
+
*
|
25 |
+
* @param bool $type
|
26 |
+
*
|
27 |
+
* @return array
|
28 |
+
*/
|
29 |
+
public function getSavedDetails($type = false)
|
30 |
+
{
|
31 |
+
return Mage::getSingleton('gene_braintree/saved')->getSavedMethodsByType($type);
|
32 |
+
}
|
33 |
+
|
34 |
+
}
|
app/code/community/Gene/Braintree/Helper/Data.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Helper_Data
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Helper_Data extends Mage_Core_Helper_Abstract
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Return all of the possible statuses as an array
|
12 |
+
*
|
13 |
+
* @return array
|
14 |
+
*/
|
15 |
+
public function getStatusesAsArray()
|
16 |
+
{
|
17 |
+
return array(
|
18 |
+
Braintree_Transaction::AUTHORIZATION_EXPIRED => $this->__('Authorization Expired'),
|
19 |
+
Braintree_Transaction::AUTHORIZING => $this->__('Authorizing'),
|
20 |
+
Braintree_Transaction::AUTHORIZED => $this->__('Authorized'),
|
21 |
+
Braintree_Transaction::GATEWAY_REJECTED => $this->__('Gateway Rejected'),
|
22 |
+
Braintree_Transaction::FAILED => $this->__('Failed'),
|
23 |
+
Braintree_Transaction::PROCESSOR_DECLINED => $this->__('Processor Declined'),
|
24 |
+
Braintree_Transaction::SETTLED => $this->__('Settled'),
|
25 |
+
Braintree_Transaction::SETTLING => $this->__('Settling'),
|
26 |
+
Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT => $this->__('Submitted For Settlement'),
|
27 |
+
Braintree_Transaction::VOIDED => $this->__('Voided'),
|
28 |
+
Braintree_Transaction::UNRECOGNIZED => $this->__('Unrecognized'),
|
29 |
+
Braintree_Transaction::SETTLEMENT_DECLINED => $this->__('Settlement Declined'),
|
30 |
+
Braintree_Transaction::SETTLEMENT_PENDING => $this->__('Settlement Pending')
|
31 |
+
);
|
32 |
+
}
|
33 |
+
}
|
app/code/community/Gene/Braintree/Model/Debug.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Debug
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Debug extends Mage_Core_Model_Abstract
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Is the debugging enabled?
|
13 |
+
*/
|
14 |
+
const GENE_BRAINTREE_DEBUG = 'payment/gene_braintree/debug';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Where shall we store the debugging information
|
18 |
+
*/
|
19 |
+
const GENE_BRAINTREE_DEBUG_FILE = 'gene_braintree.log';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Log any data passed to this method in the debug file
|
23 |
+
*
|
24 |
+
* @param $data
|
25 |
+
*/
|
26 |
+
static public function log($data)
|
27 |
+
{
|
28 |
+
// Check the debug flag in the admin
|
29 |
+
if(Mage::getStoreConfigFlag(self::GENE_BRAINTREE_DEBUG)) {
|
30 |
+
|
31 |
+
// If the data is an exception convert it to a string
|
32 |
+
if($data instanceof Exception) {
|
33 |
+
$data = $data->getMessage() . $data->getTraceAsString();
|
34 |
+
}
|
35 |
+
|
36 |
+
// Use the built in logging function
|
37 |
+
Mage::log($data, null, self::GENE_BRAINTREE_DEBUG_FILE, true);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
}
|
app/code/community/Gene/Braintree/Model/Observer.php
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Observer
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Observer
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Detect which checkout is in use and add a new layout handle
|
13 |
+
*
|
14 |
+
* @param Varien_Event_Observer $observer
|
15 |
+
*
|
16 |
+
* @return $this
|
17 |
+
*/
|
18 |
+
public function addLayoutHandle(Varien_Event_Observer $observer)
|
19 |
+
{
|
20 |
+
/* @var $action Mage_Core_Controller_Varien_Action */
|
21 |
+
$action = $observer->getAction();
|
22 |
+
|
23 |
+
/* @var $layout Mage_Core_Model_Layout */
|
24 |
+
$layout = $observer->getLayout();
|
25 |
+
|
26 |
+
// We only want to run this action on the checkout
|
27 |
+
if($action->getFullActionName() == 'checkout_onepage_index') {
|
28 |
+
|
29 |
+
// Attempt to detect Amasty_Scheckout
|
30 |
+
if (Mage::helper('core')->isModuleEnabled('Amasty_Scheckout')) {
|
31 |
+
$layout->getUpdate()->addHandle('amasty_onestep_checkout');
|
32 |
+
}
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
return $this;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Store the customer ID if set in session
|
41 |
+
*
|
42 |
+
* @param Varien_Event_Observer $observer
|
43 |
+
*/
|
44 |
+
public function completeCheckout(Varien_Event_Observer $observer)
|
45 |
+
{
|
46 |
+
// Do we have a customer ID within the session?
|
47 |
+
if(Mage::getSingleton('checkout/session')->getBraintreeCustomerId() &&
|
48 |
+
Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == Mage_Checkout_Model_Type_Onepage::METHOD_CUSTOMER) {
|
49 |
+
|
50 |
+
// Get the customer
|
51 |
+
$customer = Mage::getSingleton('customer/session')->getCustomer();
|
52 |
+
|
53 |
+
// Save the braintree customer ID
|
54 |
+
$customer->setBraintreeCustomerId(Mage::getSingleton('checkout/session')->getBraintreeCustomerId())->save();
|
55 |
+
}
|
56 |
+
|
57 |
+
// Unset the ID from the session
|
58 |
+
Mage::getSingleton('checkout/session')->unsetData('braintree_customer_id');
|
59 |
+
|
60 |
+
return $this;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Capture payment on shipment if set
|
65 |
+
*
|
66 |
+
* @param Varien_Event_Observer $observer
|
67 |
+
*
|
68 |
+
* @return $this
|
69 |
+
*/
|
70 |
+
public function captureBraintreePayment(Varien_Event_Observer $observer)
|
71 |
+
{
|
72 |
+
/* @var $shipment Mage_Sales_Model_Order_Shipment */
|
73 |
+
$shipment = $observer->getEvent()->getShipment();
|
74 |
+
|
75 |
+
/* @var $order Mage_Sales_Model_Order */
|
76 |
+
$order = $shipment->getOrder();
|
77 |
+
|
78 |
+
// Should we capture the payment in shipment?
|
79 |
+
if($this->shouldCaptureShipment($order)) {
|
80 |
+
|
81 |
+
// Check the order can be invoiced
|
82 |
+
if($order->canInvoice()) {
|
83 |
+
|
84 |
+
/* @var @invoice Mage_Sales_Model_Order_Invoice */
|
85 |
+
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
|
86 |
+
|
87 |
+
// Check the invoice has items to invoice
|
88 |
+
if ($invoice->getTotalQty()) {
|
89 |
+
|
90 |
+
// Set the requested capture case
|
91 |
+
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_ONLINE);
|
92 |
+
|
93 |
+
// Register the invoice
|
94 |
+
$invoice->register();
|
95 |
+
|
96 |
+
// Save the transaction
|
97 |
+
$transactionSave = Mage::getModel('core/resource_transaction')
|
98 |
+
->addObject($invoice)
|
99 |
+
->addObject($invoice->getOrder());
|
100 |
+
|
101 |
+
// Save the transaction
|
102 |
+
$transactionSave->save();
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
}
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
return $this;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Store the currency mapping as a JSON string
|
115 |
+
*
|
116 |
+
* @param \Varien_Event_Observer $observer
|
117 |
+
*
|
118 |
+
* @return $this
|
119 |
+
*/
|
120 |
+
public function modifyCurrencyMapping(Varien_Event_Observer $observer)
|
121 |
+
{
|
122 |
+
|
123 |
+
return $this;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Should we capture the payment?
|
128 |
+
*
|
129 |
+
* @param $order Mage_Sales_Model_Order
|
130 |
+
*
|
131 |
+
* @return bool
|
132 |
+
*/
|
133 |
+
private function shouldCaptureShipment($order)
|
134 |
+
{
|
135 |
+
// Check the store configuration settings are set to capture shipment
|
136 |
+
if(Mage::getStoreConfig(Gene_Braintree_Model_Source_Creditcard_PaymentAction::PAYMENT_ACTION_XML_PATH, $order->getStoreId()) == Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE
|
137 |
+
&& Mage::getStoreConfig(Gene_Braintree_Model_Source_Creditcard_CaptureAction::CAPTURE_ACTION_XML_PATH, $order->getStoreId()) == Gene_Braintree_Model_Source_Creditcard_CaptureAction::CAPTURE_SHIPMENT)
|
138 |
+
{
|
139 |
+
return true;
|
140 |
+
}
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
}
|
app/code/community/Gene/Braintree/Model/Paymentmethod/Abstract.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Paymentmethod_Abstract
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
abstract class Gene_Braintree_Model_Paymentmethod_Abstract extends Mage_Payment_Model_Method_Abstract
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Verify that the module has been setup
|
13 |
+
*
|
14 |
+
* @param null $quote
|
15 |
+
*
|
16 |
+
* @return bool
|
17 |
+
*/
|
18 |
+
public function isAvailable($quote = null)
|
19 |
+
{
|
20 |
+
// Check Magento's internal methods allow us to run
|
21 |
+
if(parent::isAvailable($quote)) {
|
22 |
+
|
23 |
+
// Validate the configuration is okay
|
24 |
+
return $this->_getWrapper()->validateCredentialsOnce();
|
25 |
+
|
26 |
+
} else {
|
27 |
+
|
28 |
+
// Otherwise it's a no
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Return the helper
|
35 |
+
*
|
36 |
+
* @return Mage_Payment_Helper_Data
|
37 |
+
*/
|
38 |
+
protected function _getHelper()
|
39 |
+
{
|
40 |
+
return Mage::helper('gene_braintree');
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Return the wrapper class
|
45 |
+
*
|
46 |
+
* @return Gene_Braintree_Model_Wrapper_Braintree
|
47 |
+
*/
|
48 |
+
protected function _getWrapper()
|
49 |
+
{
|
50 |
+
return Mage::getSingleton('gene_braintree/wrapper_braintree');
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Return configuration values
|
55 |
+
*
|
56 |
+
* @param $value
|
57 |
+
*
|
58 |
+
* @return mixed
|
59 |
+
*/
|
60 |
+
protected function _getConfig($key)
|
61 |
+
{
|
62 |
+
return Mage::getStoreConfig('payment/'.$this->_code.'/'.$key);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Is the vault enabled?
|
67 |
+
*
|
68 |
+
* @return bool
|
69 |
+
*/
|
70 |
+
public function isVaultEnabled()
|
71 |
+
{
|
72 |
+
return $this->_getConfig('use_vault');
|
73 |
+
}
|
74 |
+
|
75 |
+
}
|
app/code/community/Gene/Braintree/Model/Paymentmethod/Creditcard.php
ADDED
@@ -0,0 +1,380 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Paymentmethod_Creditcard
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Paymentmethod_Creditcard extends Gene_Braintree_Model_Paymentmethod_Abstract
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Setup block types
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $_formBlockType = 'gene_braintree/creditcard';
|
16 |
+
protected $_infoBlockType = 'gene_braintree/creditcard_info';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Set the code
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
protected $_code = 'gene_braintree_creditcard';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Payment Method features
|
27 |
+
*
|
28 |
+
* @var bool
|
29 |
+
*/
|
30 |
+
protected $_isGateway = false;
|
31 |
+
protected $_canOrder = false;
|
32 |
+
protected $_canAuthorize = true;
|
33 |
+
protected $_canCapture = true;
|
34 |
+
protected $_canCapturePartial = true;
|
35 |
+
protected $_canRefund = false;
|
36 |
+
protected $_canRefundInvoicePartial = false;
|
37 |
+
protected $_canVoid = false;
|
38 |
+
protected $_canUseInternal = true;
|
39 |
+
protected $_canUseCheckout = true;
|
40 |
+
protected $_canUseForMultishipping = false;
|
41 |
+
protected $_isInitializeNeeded = false;
|
42 |
+
protected $_canFetchTransactionInfo = false;
|
43 |
+
protected $_canReviewPayment = false;
|
44 |
+
protected $_canCreateBillingAgreement = false;
|
45 |
+
protected $_canManageRecurringProfiles = false;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* If we're trying to charge a 3D secure card in the vault we need to build a special nonce
|
49 |
+
*
|
50 |
+
* @param $paymentMethodToken
|
51 |
+
*
|
52 |
+
* @return mixed
|
53 |
+
*/
|
54 |
+
public function getThreeDSecureVaultNonce($paymentMethodToken)
|
55 |
+
{
|
56 |
+
return $this->_getWrapper()->getThreeDSecureVaultNonce($paymentMethodToken);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Is 3D secure enabled?
|
61 |
+
*
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
+
public function is3DEnabled()
|
65 |
+
{
|
66 |
+
// 3D secure can never be enabled for the admin
|
67 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
68 |
+
return false;
|
69 |
+
}
|
70 |
+
|
71 |
+
if($this->_getConfig('threedsecure')) {
|
72 |
+
return true;
|
73 |
+
}
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Do we need to send the CCV, which Braintree calls a CVV?
|
79 |
+
*
|
80 |
+
* @return mixed
|
81 |
+
*/
|
82 |
+
public function requireCcv()
|
83 |
+
{
|
84 |
+
if($this->_getConfig('useccv')) {
|
85 |
+
return true;
|
86 |
+
}
|
87 |
+
return false;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Psuedo _authorize function so we can pass in extra data
|
92 |
+
* @param Varien_Object $payment
|
93 |
+
* @param $amount
|
94 |
+
* @param bool $shouldCapture
|
95 |
+
*
|
96 |
+
* @throws Mage_Core_Exception
|
97 |
+
*/
|
98 |
+
protected function _authorize(Varien_Object $payment, $amount, $shouldCapture = false)
|
99 |
+
{
|
100 |
+
// Retrieve the post data from the request
|
101 |
+
$paymentPost = Mage::app()->getRequest()->getPost('payment');
|
102 |
+
|
103 |
+
// Confirm that we have a nonce from Braintree
|
104 |
+
if(!isset($paymentPost['card_payment_method_token']) || (isset($paymentPost['card_payment_method_token']) && $paymentPost['card_payment_method_token'] == 'threedsecure')) {
|
105 |
+
if ((!isset($paymentPost['payment_method_nonce']) || empty($paymentPost['payment_method_nonce']))) {
|
106 |
+
Mage::throwException(
|
107 |
+
$this->_getHelper()->__('Your card payment has failed, please try again.')
|
108 |
+
);
|
109 |
+
}
|
110 |
+
} else if(isset($paymentPost['card_payment_method_token']) && empty($paymentPost['card_payment_method_token'])) {
|
111 |
+
Mage::throwException(
|
112 |
+
$this->_getHelper()->__('Your card payment has failed, please try again.')
|
113 |
+
);
|
114 |
+
}
|
115 |
+
|
116 |
+
// Get the device data for fraud screening
|
117 |
+
$deviceData = Mage::app()->getRequest()->getPost('device_data');
|
118 |
+
|
119 |
+
// Init the environment
|
120 |
+
$this->_getWrapper()->init();
|
121 |
+
|
122 |
+
// Attempt to create the sale
|
123 |
+
try {
|
124 |
+
|
125 |
+
// Pass over the CVV/CCV
|
126 |
+
if($this->requireCcv() && isset($paymentPost['cc_cid'])) {
|
127 |
+
|
128 |
+
$paymentArray['cvv'] = $paymentPost['cc_cid'];
|
129 |
+
|
130 |
+
} else if($this->requireCcv() && !isset($paymentPost['cc_cid']) && empty($paymentPost['card_payment_method_token'])) {
|
131 |
+
|
132 |
+
// Log it
|
133 |
+
Gene_Braintree_Model_Debug::log('CVV required but not present in request');
|
134 |
+
|
135 |
+
// Politely inform the user
|
136 |
+
Mage::throwException(
|
137 |
+
$this->_getHelper()->__('We require a CVV when creating card transactions.')
|
138 |
+
);
|
139 |
+
|
140 |
+
}
|
141 |
+
|
142 |
+
// Check to see whether we're using a payment method token?
|
143 |
+
if(isset($paymentPost['card_payment_method_token']) && !empty($paymentPost['card_payment_method_token']) && !in_array($paymentPost['card_payment_method_token'], array('other', 'threedsecure'))) {
|
144 |
+
|
145 |
+
// Build our payment array
|
146 |
+
$paymentArray = array(
|
147 |
+
'paymentMethodToken' => $paymentPost['card_payment_method_token'],
|
148 |
+
);
|
149 |
+
|
150 |
+
unset($paymentArray['cvv']);
|
151 |
+
|
152 |
+
} else {
|
153 |
+
|
154 |
+
// Build our payment array with a nonce
|
155 |
+
$paymentArray = array(
|
156 |
+
'paymentMethodNonce' => $paymentPost['payment_method_nonce']
|
157 |
+
);
|
158 |
+
|
159 |
+
}
|
160 |
+
|
161 |
+
// The 3D secure variable
|
162 |
+
$threeDSecure = $this->is3DEnabled();
|
163 |
+
|
164 |
+
// If the user is using a stored card with 3D secure, enable it in the request and remove CVV
|
165 |
+
if(isset($paymentPost['card_payment_method_token']) && $paymentPost['card_payment_method_token'] == 'threedsecure') {
|
166 |
+
|
167 |
+
// If we're using 3D secure token card don't send CVV
|
168 |
+
unset($paymentArray['cvv']);
|
169 |
+
|
170 |
+
// Force 3D secure on
|
171 |
+
$threeDSecure = true;
|
172 |
+
|
173 |
+
} elseif(isset($paymentPost['card_payment_method_token']) && !empty($paymentPost['card_payment_method_token']) && $paymentPost['card_payment_method_token'] != 'other') {
|
174 |
+
|
175 |
+
// Force 3D secure off
|
176 |
+
$threeDSecure = false;
|
177 |
+
}
|
178 |
+
|
179 |
+
// Retrieve the amount we should capture
|
180 |
+
$amount = $this->_getWrapper()->getCaptureAmount($payment->getOrder(), $amount);
|
181 |
+
|
182 |
+
// Build up the sale array
|
183 |
+
$saleArray = $this->_getWrapper()->buildSale(
|
184 |
+
$amount,
|
185 |
+
$paymentArray,
|
186 |
+
$payment->getOrder(),
|
187 |
+
$shouldCapture,
|
188 |
+
$deviceData,
|
189 |
+
($this->isVaultEnabled() && isset($paymentPost['save_card']) && $paymentPost['save_card'] == 1),
|
190 |
+
$threeDSecure
|
191 |
+
);
|
192 |
+
|
193 |
+
// Pass the sale array into a varien object
|
194 |
+
$request = new Varien_Object();
|
195 |
+
$request->setData('sale_array', $saleArray);
|
196 |
+
|
197 |
+
// Dispatch event for modifying the sale array
|
198 |
+
Mage::dispatchEvent('gene_braintree_creditcard_sale_array', array('payment' => $payment, 'request' => $request));
|
199 |
+
|
200 |
+
// Pull the saleArray back out
|
201 |
+
$saleArray = $request->getData('sale_array');
|
202 |
+
|
203 |
+
// Log the initial sale array, no protected data is included
|
204 |
+
Gene_Braintree_Model_Debug::log(array('_authorize:saleArray' => $saleArray));
|
205 |
+
|
206 |
+
// Attempt to create the sale
|
207 |
+
$result = $this->_getWrapper()->makeSale(
|
208 |
+
$saleArray
|
209 |
+
);
|
210 |
+
|
211 |
+
} catch (Exception $e) {
|
212 |
+
|
213 |
+
// Dispatch an event for when a payment fails
|
214 |
+
Mage::dispatchEvent('gene_braintree_creditcard_failed_exception', array('payment' => $payment, 'exception' => $e));
|
215 |
+
|
216 |
+
// If there's an error
|
217 |
+
Gene_Braintree_Model_Debug::log($e);
|
218 |
+
|
219 |
+
Mage::throwException(
|
220 |
+
$this->_getHelper()->__('There was an issue whilst trying to process your card payment, please try again or another method.')
|
221 |
+
);
|
222 |
+
}
|
223 |
+
|
224 |
+
// Log the initial sale array, no protected data is included
|
225 |
+
Gene_Braintree_Model_Debug::log(array('_authorize:result' => $result));
|
226 |
+
|
227 |
+
// If the sale has failed
|
228 |
+
if ($result->success != true) {
|
229 |
+
|
230 |
+
// Dispatch an event for when a payment fails
|
231 |
+
Mage::dispatchEvent('gene_braintree_creditcard_failed', array('payment' => $payment, 'result' => $result));
|
232 |
+
|
233 |
+
// Return a different message for declined cards
|
234 |
+
if(isset($result->transaction->status) && $result->transaction->status == Braintree_Transaction::PROCESSOR_DECLINED) {
|
235 |
+
Mage::throwException($this->_getHelper()->__('Your transaction has been declined, please try another payment method or contacting your issuing bank.'));
|
236 |
+
}
|
237 |
+
|
238 |
+
Mage::throwException($this->_getHelper()->__('%s. Please try again or attempt refreshing the page.', $result->message));
|
239 |
+
}
|
240 |
+
|
241 |
+
// If 3D is enabled and the transaction gets a rejection reason
|
242 |
+
if($this->is3DEnabled()) {
|
243 |
+
|
244 |
+
// Check the rejection reason
|
245 |
+
if (isset($result->transaction) && $result->transaction->gatewayRejectionReason == Braintree_Transaction::THREE_D_SECURE) {
|
246 |
+
|
247 |
+
// An event for when 3D secure fails
|
248 |
+
Mage::dispatchEvent('gene_braintree_creditcard_failed_threed', array('payment' => $payment, 'result' => $result));
|
249 |
+
|
250 |
+
// Log it
|
251 |
+
Gene_Braintree_Model_Debug::log('Transaction failed with 3D secure');
|
252 |
+
|
253 |
+
// Politely inform the user
|
254 |
+
Mage::throwException(
|
255 |
+
$this->_getHelper()->__('Your 3D secure verification has failed, please try using another card, or payment method.')
|
256 |
+
);
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
$this->_processSuccessResult($payment, $result, $amount);
|
261 |
+
|
262 |
+
return $this;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Authorize the requested amount
|
267 |
+
* @param Varien_Object $payment
|
268 |
+
* @param float $amount
|
269 |
+
*
|
270 |
+
* @return Mage_Payment_Model_Abstract|void
|
271 |
+
* @throws Mage_Core_Exception
|
272 |
+
*/
|
273 |
+
public function authorize(Varien_Object $payment, $amount)
|
274 |
+
{
|
275 |
+
$this->_authorize($payment, $amount, false);
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Process capturing of a payment
|
280 |
+
* @param Varien_Object $payment
|
281 |
+
* @param float $amount
|
282 |
+
*
|
283 |
+
* @return Mage_Payment_Model_Abstract|void
|
284 |
+
*/
|
285 |
+
public function capture(Varien_Object $payment, $amount)
|
286 |
+
{
|
287 |
+
// Has the payment already been authorized?
|
288 |
+
if ($payment->getCcTransId()) {
|
289 |
+
|
290 |
+
// Init the environment
|
291 |
+
$result = $this->_getWrapper()->init()->submitForSettlement($payment->getCcTransId(), $amount);
|
292 |
+
|
293 |
+
// Log the result
|
294 |
+
Gene_Braintree_Model_Debug::log(array('capture:submitForSettlement' => $result));
|
295 |
+
|
296 |
+
if($result->success) {
|
297 |
+
$this->_processSuccessResult($payment, $result, $amount);
|
298 |
+
} else if($result->errors->deepSize() > 0) {
|
299 |
+
Mage::throwException($result->errors);
|
300 |
+
} else {
|
301 |
+
Mage::throwException($result->transaction->processorSettlementResponseCode.': '.$result->transaction->processorSettlementResponseText);
|
302 |
+
}
|
303 |
+
|
304 |
+
} else {
|
305 |
+
// Otherwise we need to do an auth & capture at once
|
306 |
+
$this->_authorize($payment, $amount, true);
|
307 |
+
}
|
308 |
+
|
309 |
+
return $this;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Processes successful authorize/clone result
|
314 |
+
*
|
315 |
+
* @param Varien_Object $payment
|
316 |
+
* @param Braintree_Result_Successful $result
|
317 |
+
* @param decimal amount
|
318 |
+
* @return Varien_Object
|
319 |
+
*/
|
320 |
+
protected function _processSuccessResult(Varien_Object $payment, $result, $amount)
|
321 |
+
{
|
322 |
+
// Pass an event if the payment was a success
|
323 |
+
Mage::dispatchEvent('gene_braintree_creditcard_success', array('payment' => $payment, 'result' => $result, 'amount' => $amount));
|
324 |
+
|
325 |
+
// Set some basic information about the payment
|
326 |
+
$payment->setStatus(self::STATUS_APPROVED)
|
327 |
+
->setCcTransId($result->transaction->id)
|
328 |
+
->setLastTransId($result->transaction->id)
|
329 |
+
->setTransactionId($result->transaction->id)
|
330 |
+
->setIsTransactionClosed(0)
|
331 |
+
->setAmount($amount)
|
332 |
+
->setShouldCloseParentTransaction(false);
|
333 |
+
|
334 |
+
// Set information about the card
|
335 |
+
$payment->setCcLast4($result->transaction->creditCardDetails->last4)
|
336 |
+
->setCcType($result->transaction->creditCardDetails->cardType)
|
337 |
+
->setCcExpMonth($result->transaction->creditCardDetails->expirationMonth)
|
338 |
+
->setCcExpYear($result->transaction->creditCardDetails->expirationYear);
|
339 |
+
|
340 |
+
// Additional information to store
|
341 |
+
$additionalInfo = array();
|
342 |
+
|
343 |
+
// The fields within the transaction to log
|
344 |
+
$storeFields = array(
|
345 |
+
'avsErrorResponseCode',
|
346 |
+
'avsPostalCodeResponseCode',
|
347 |
+
'avsStreetAddressResponseCode',
|
348 |
+
'cvvResponseCode',
|
349 |
+
'gatewayRejectionReason',
|
350 |
+
'processorAuthorizationCode',
|
351 |
+
'processorResponseCode',
|
352 |
+
'processorResponseText',
|
353 |
+
'threeDSecure'
|
354 |
+
);
|
355 |
+
|
356 |
+
// If 3D secure is enabled, presume it's passed
|
357 |
+
if($this->is3DEnabled()) {
|
358 |
+
$additionalInfo['threeDSecure'] = Mage::helper('gene_braintree')->__('Passed');
|
359 |
+
}
|
360 |
+
|
361 |
+
// Iterate through and pull out any data we want
|
362 |
+
foreach($storeFields as $storeField) {
|
363 |
+
if(!empty($result->transaction->{$storeField})) {
|
364 |
+
$additionalInfo[$storeField] = $result->transaction->{$storeField};
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
// Check it's not empty and store it
|
369 |
+
if(!empty($additionalInfo)) {
|
370 |
+
$payment->setAdditionalInformation($additionalInfo);
|
371 |
+
}
|
372 |
+
|
373 |
+
if (isset($result->transaction->creditCard['token']) && $result->transaction->creditCard['token']) {
|
374 |
+
$payment->setAdditionalInformation('token', $result->transaction->creditCard['token']);
|
375 |
+
}
|
376 |
+
|
377 |
+
return $payment;
|
378 |
+
}
|
379 |
+
|
380 |
+
}
|
app/code/community/Gene/Braintree/Model/Paymentmethod/Paypal.php
ADDED
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Paymentmethod_Paypal
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Paymentmethod_Paypal extends Gene_Braintree_Model_Paymentmethod_Abstract
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Setup block types
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $_formBlockType = 'gene_braintree/paypal';
|
16 |
+
protected $_infoBlockType = 'gene_braintree/paypal_info';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Set the code
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
protected $_code = 'gene_braintree_paypal';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Payment Method features
|
27 |
+
*
|
28 |
+
* @var bool
|
29 |
+
*/
|
30 |
+
protected $_isGateway = false;
|
31 |
+
protected $_canOrder = false;
|
32 |
+
protected $_canAuthorize = false;
|
33 |
+
protected $_canCapture = true;
|
34 |
+
protected $_canCapturePartial = false;
|
35 |
+
protected $_canRefund = false;
|
36 |
+
protected $_canRefundInvoicePartial = false;
|
37 |
+
protected $_canVoid = false;
|
38 |
+
protected $_canUseInternal = false;
|
39 |
+
protected $_canUseCheckout = true;
|
40 |
+
protected $_canUseForMultishipping = false;
|
41 |
+
protected $_isInitializeNeeded = false;
|
42 |
+
protected $_canFetchTransactionInfo = false;
|
43 |
+
protected $_canReviewPayment = false;
|
44 |
+
protected $_canCreateBillingAgreement = false;
|
45 |
+
protected $_canManageRecurringProfiles = false;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Is the vault enabled?
|
49 |
+
*
|
50 |
+
* @return bool
|
51 |
+
*/
|
52 |
+
public function isVaultEnabled()
|
53 |
+
{
|
54 |
+
if ($this->_getConfig('payment_type') == Gene_Braintree_Model_Source_Paypal_Paymenttype::GENE_BRAINTREE_PAYPAL_FUTURE_PAYMENTS
|
55 |
+
&& $this->_getConfig('use_vault'))
|
56 |
+
{
|
57 |
+
return true;
|
58 |
+
}
|
59 |
+
return false;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Capture the payment on the checkout page
|
64 |
+
*
|
65 |
+
* @param Varien_Object $payment
|
66 |
+
* @param float $amount
|
67 |
+
*
|
68 |
+
* @return Mage_Payment_Model_Abstract
|
69 |
+
*/
|
70 |
+
public function capture(Varien_Object $payment, $amount)
|
71 |
+
{
|
72 |
+
// Retrieve the payment data from the request
|
73 |
+
$paymentPost = Mage::app()->getRequest()->getPost('payment');
|
74 |
+
|
75 |
+
// Confirm that we have a nonce from Braintree
|
76 |
+
if(!isset($paymentPost['paypal_payment_method_token'])) {
|
77 |
+
if ((!isset($paymentPost['payment_method_nonce']) || empty($paymentPost['payment_method_nonce']))) {
|
78 |
+
Mage::throwException(
|
79 |
+
$this->_getHelper()->__('There has been an issue processing your PayPal payment, please try again.')
|
80 |
+
);
|
81 |
+
}
|
82 |
+
} else if(isset($paymentPost['paypal_payment_method_token']) && empty($paymentPost['paypal_payment_method_token'])) {
|
83 |
+
Mage::throwException(
|
84 |
+
$this->_getHelper()->__('There has been an issue processing your PayPal payment, please try again.')
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
// Get the device data for fraud screening
|
89 |
+
$deviceData = Mage::app()->getRequest()->getPost('device_data');
|
90 |
+
|
91 |
+
// Init the environment
|
92 |
+
$this->_getWrapper()->init();
|
93 |
+
|
94 |
+
if(isset($paymentPost['paypal_payment_method_token']) && !empty($paymentPost['paypal_payment_method_token']) && $paymentPost['paypal_payment_method_token'] != 'other') {
|
95 |
+
$paymentArray = array(
|
96 |
+
'paymentMethodToken' => $paymentPost['paypal_payment_method_token']
|
97 |
+
);
|
98 |
+
} else {
|
99 |
+
$paymentArray = array(
|
100 |
+
'paymentMethodNonce' => $paymentPost['payment_method_nonce']
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
// Retrieve the amount we should capture
|
105 |
+
$amount = $this->_getWrapper()->getCaptureAmount($payment->getOrder(), $amount);
|
106 |
+
|
107 |
+
// Attempt to create the sale
|
108 |
+
try {
|
109 |
+
// Build the array for the sale
|
110 |
+
$saleArray = $this->_getWrapper()->buildSale(
|
111 |
+
$amount,
|
112 |
+
$paymentArray,
|
113 |
+
$payment->getOrder(),
|
114 |
+
true,
|
115 |
+
$deviceData,
|
116 |
+
($this->isVaultEnabled() && isset($paymentPost['save_paypal']) && $paymentPost['save_paypal'] == 1)
|
117 |
+
);
|
118 |
+
|
119 |
+
// Pass the sale array into a varien object
|
120 |
+
$request = new Varien_Object();
|
121 |
+
$request->setData('sale_array', $saleArray);
|
122 |
+
|
123 |
+
// Dispatch event for modifying the sale array
|
124 |
+
Mage::dispatchEvent('gene_braintree_paypal_sale_array', array('payment' => $payment, 'request' => $request));
|
125 |
+
|
126 |
+
// Pull the saleArray back out
|
127 |
+
$saleArray = $request->getData('sale_array');
|
128 |
+
|
129 |
+
// Log the initial sale array, no protected data is included
|
130 |
+
Gene_Braintree_Model_Debug::log(array('saleArray' => $saleArray));
|
131 |
+
|
132 |
+
// Attempt to create the sale
|
133 |
+
$result = $this->_getWrapper()->makeSale(
|
134 |
+
$saleArray
|
135 |
+
);
|
136 |
+
} catch (Exception $e) {
|
137 |
+
|
138 |
+
// Dispatch an event for when a payment fails
|
139 |
+
Mage::dispatchEvent('gene_braintree_paypal_failed_exception', array('payment' => $payment, 'exception' => $e));
|
140 |
+
|
141 |
+
// If there's an error
|
142 |
+
Gene_Braintree_Model_Debug::log($e);
|
143 |
+
|
144 |
+
Mage::throwException(
|
145 |
+
$this->_getHelper()->__('We were unable to complete your purchase through PayPal, please try again or an alternative payment method.')
|
146 |
+
);
|
147 |
+
}
|
148 |
+
|
149 |
+
// Log the result
|
150 |
+
Gene_Braintree_Model_Debug::log(array('result' => $result));
|
151 |
+
|
152 |
+
// If the sale has failed
|
153 |
+
if ($result->success != true) {
|
154 |
+
|
155 |
+
// Dispatch an event for when a payment fails
|
156 |
+
Mage::dispatchEvent('gene_braintree_paypal_failed', array('payment' => $payment, 'result' => $result));
|
157 |
+
|
158 |
+
Mage::throwException($this->_getHelper()->__('%s. Please try again or attempt refreshing the page.', $result->message));
|
159 |
+
}
|
160 |
+
|
161 |
+
// Finish of the order
|
162 |
+
$this->_processSuccessResult($payment, $result, $amount);
|
163 |
+
|
164 |
+
return $this;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Process a successful result from the sale request
|
169 |
+
*
|
170 |
+
* @param Varien_Object $payment
|
171 |
+
* @param Braintree_Result_Successful $result
|
172 |
+
* @param $amount
|
173 |
+
*
|
174 |
+
* @return Varien_Object
|
175 |
+
*/
|
176 |
+
protected function _processSuccessResult(Varien_Object $payment, $result, $amount)
|
177 |
+
{
|
178 |
+
// Pass an event if the payment was a success
|
179 |
+
Mage::dispatchEvent('gene_braintree_paypal_success', array('payment' => $payment, 'result' => $result, 'amount' => $amount));
|
180 |
+
|
181 |
+
// Set some basic things
|
182 |
+
$payment->setStatus(self::STATUS_APPROVED)
|
183 |
+
->setCcTransId($result->transaction->id)
|
184 |
+
->setLastTransId($result->transaction->id)
|
185 |
+
->setTransactionId($result->transaction->id)
|
186 |
+
->setIsTransactionClosed(0)
|
187 |
+
->setAmount($amount)
|
188 |
+
->setShouldCloseParentTransaction(false);
|
189 |
+
|
190 |
+
// Set the additioanl information about the customers PayPal account
|
191 |
+
$payment->setAdditionalInformation(
|
192 |
+
array(
|
193 |
+
'paypal_email' => $result->transaction->paypal['payerEmail'],
|
194 |
+
'payment_id' => $result->transaction->paypal['paymentId'],
|
195 |
+
'authorization_id' => $result->transaction->paypal['authorizationId'],
|
196 |
+
)
|
197 |
+
);
|
198 |
+
|
199 |
+
// Store the PayPal token if we have one
|
200 |
+
if (isset($result->transaction->paypal['token']) && !empty($result->transaction->paypal['token'])) {
|
201 |
+
$payment->setAdditionalInformation('token', $result->transaction->paypal['token']);
|
202 |
+
}
|
203 |
+
|
204 |
+
// Save the payment data
|
205 |
+
$payment->save();
|
206 |
+
|
207 |
+
return $payment;
|
208 |
+
}
|
209 |
+
|
210 |
+
}
|
app/code/community/Gene/Braintree/Model/Saved.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Gene_Braintree_Model_Saved
|
4 |
+
*
|
5 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
6 |
+
*/
|
7 |
+
class Gene_Braintree_Model_Saved extends Mage_Core_Model_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
/**
|
11 |
+
* The ID's associated with the two different payment methods
|
12 |
+
*/
|
13 |
+
const SAVED_PAYPAL_ID = 1;
|
14 |
+
const SAVED_CREDITCARD_ID = 2;
|
15 |
+
|
16 |
+
private $savedAccounts = false;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Get the current customers saved cards
|
20 |
+
*
|
21 |
+
* @return array
|
22 |
+
*/
|
23 |
+
public function getCustomerSavedPaymentMethods()
|
24 |
+
{
|
25 |
+
// Grab an instance of the customers session
|
26 |
+
$customerSession = Mage::getSingleton('customer/session');
|
27 |
+
|
28 |
+
// You can only store cards if you're logged in
|
29 |
+
if($customerSession->isLoggedIn() && $customerSession->getCustomer()->getBraintreeCustomerId()) {
|
30 |
+
|
31 |
+
if(!$this->savedAccounts) {
|
32 |
+
|
33 |
+
// Grab a new instance of the wrapper
|
34 |
+
$wrapper = Mage::getModel('gene_braintree/wrapper_braintree');
|
35 |
+
|
36 |
+
// Init the braintree wrapper
|
37 |
+
$wrapper->init();
|
38 |
+
|
39 |
+
// Try and load the customer from Braintrees side
|
40 |
+
if ($customer = $wrapper->getCustomer($customerSession->getCustomer()->getBraintreeCustomerId())) {
|
41 |
+
|
42 |
+
// Assign them into our model
|
43 |
+
$this->savedAccounts = array_merge($customer->creditCards, $customer->paypalAccounts);
|
44 |
+
}
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
return $this->savedAccounts;
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
return false;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Return a boolean value on whether the customer has a certain type of payment method
|
57 |
+
*
|
58 |
+
* @param bool $type
|
59 |
+
*
|
60 |
+
* @return bool|int
|
61 |
+
*/
|
62 |
+
public function hasType($type = false)
|
63 |
+
{
|
64 |
+
// If no type is set just count the saved methods
|
65 |
+
if(!$type) {
|
66 |
+
if(!$this->getCustomerSavedPaymentMethods()) {
|
67 |
+
return false;
|
68 |
+
}
|
69 |
+
return count($this->getCustomerSavedPaymentMethods());
|
70 |
+
}
|
71 |
+
|
72 |
+
// Check there are some saved accounts
|
73 |
+
if($savedAccounts = $this->getCustomerSavedPaymentMethods()) {
|
74 |
+
|
75 |
+
// Iterate through the saved accounts
|
76 |
+
foreach ($savedAccounts as $savedAccount) {
|
77 |
+
|
78 |
+
// Check which type we're after
|
79 |
+
if ($type == Gene_Braintree_Model_Saved::SAVED_CREDITCARD_ID) {
|
80 |
+
if ($savedAccount instanceof Braintree_CreditCard) {
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
} elseif ($type == Gene_Braintree_Model_Saved::SAVED_PAYPAL_ID) {
|
84 |
+
if ($savedAccount instanceof Braintree_PayPalAccount) {
|
85 |
+
return true;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
return false;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Return only those accounts which are a certain type
|
97 |
+
|
98 |
+
* @param $type
|
99 |
+
*
|
100 |
+
* @return array
|
101 |
+
*/
|
102 |
+
public function getSavedMethodsByType($type = false)
|
103 |
+
{
|
104 |
+
if(!$type) {
|
105 |
+
return $this->getCustomerSavedPaymentMethods();
|
106 |
+
}
|
107 |
+
|
108 |
+
// Start up our new collection
|
109 |
+
$savedDetails = array();
|
110 |
+
|
111 |
+
if($this->getCustomerSavedPaymentMethods()) {
|
112 |
+
foreach ($this->getCustomerSavedPaymentMethods() as $savedAccount) {
|
113 |
+
|
114 |
+
// Check which type we're after
|
115 |
+
if ($type == Gene_Braintree_Model_Saved::SAVED_CREDITCARD_ID) {
|
116 |
+
if ($savedAccount instanceof Braintree_CreditCard) {
|
117 |
+
$savedDetails[] = $savedAccount;
|
118 |
+
}
|
119 |
+
} elseif ($type == Gene_Braintree_Model_Saved::SAVED_PAYPAL_ID) {
|
120 |
+
if ($savedAccount instanceof Braintree_PayPalAccount) {
|
121 |
+
$savedDetails[] = $savedAccount;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
return $savedDetails;
|
128 |
+
}
|
129 |
+
|
130 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Cctype.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Source_Cctype
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Source_Cctype extends Mage_Payment_Model_Source_Cctype
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Allowed credit card types
|
12 |
+
* This list includes a separate entry for Maestro
|
13 |
+
*
|
14 |
+
* @return array
|
15 |
+
*/
|
16 |
+
public function getAllowedTypes()
|
17 |
+
{
|
18 |
+
return array(
|
19 |
+
'VI',
|
20 |
+
'MC',
|
21 |
+
'AE',
|
22 |
+
'DI',
|
23 |
+
'JCB',
|
24 |
+
'OT',
|
25 |
+
'ME'
|
26 |
+
);
|
27 |
+
}
|
28 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Creditcard/CaptureAction.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Source_Creditcard_CaptureAction
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Source_Creditcard_CaptureAction
|
9 |
+
{
|
10 |
+
|
11 |
+
const CAPTURE_ACTION_XML_PATH = 'payment/gene_braintree_creditcard/capture_action';
|
12 |
+
|
13 |
+
const CAPTURE_INVOICE = 'invoice';
|
14 |
+
const CAPTURE_SHIPMENT = 'shipment';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Possible actions on order place
|
18 |
+
*
|
19 |
+
* @return array
|
20 |
+
*/
|
21 |
+
public function toOptionArray()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
array(
|
25 |
+
'value' => self::CAPTURE_INVOICE,
|
26 |
+
'label' => Mage::helper('gene_braintree')->__('Invoice')
|
27 |
+
),
|
28 |
+
array(
|
29 |
+
'value' => self::CAPTURE_SHIPMENT,
|
30 |
+
'label' => Mage::helper('gene_braintree')->__('Shipment')
|
31 |
+
),
|
32 |
+
);
|
33 |
+
}
|
34 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Creditcard/PaymentAction.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Source_Creditcard_PaymentAction
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Source_Creditcard_PaymentAction
|
9 |
+
{
|
10 |
+
|
11 |
+
const PAYMENT_ACTION_XML_PATH = 'payment/gene_braintree_creditcard/payment_action';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Possible actions on order place
|
15 |
+
*
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
public function toOptionArray()
|
19 |
+
{
|
20 |
+
return array(
|
21 |
+
array(
|
22 |
+
'value' => Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE,
|
23 |
+
'label' => Mage::helper('gene_braintree')->__('Authorize')
|
24 |
+
),
|
25 |
+
array(
|
26 |
+
'value' => Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE,
|
27 |
+
'label' => Mage::helper('gene_braintree')->__('Authorize & Capture')
|
28 |
+
),
|
29 |
+
);
|
30 |
+
}
|
31 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Environment.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Braintree_Payments_Model_Source_Environment
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Source_Environment
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Display both sandbox and production values
|
12 |
+
*
|
13 |
+
* @return array
|
14 |
+
*/
|
15 |
+
public function toOptionArray()
|
16 |
+
{
|
17 |
+
return array(
|
18 |
+
array(
|
19 |
+
'value' => 'sandbox',
|
20 |
+
'label' => Mage::helper('gene_braintree')->__('Sandbox'),
|
21 |
+
),
|
22 |
+
array(
|
23 |
+
'value' => 'production',
|
24 |
+
'label' => Mage::helper('gene_braintree')->__('Production')
|
25 |
+
)
|
26 |
+
);
|
27 |
+
}
|
28 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Paypal/Locale.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Source_Paypal_Locale
|
5 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
6 |
+
*/
|
7 |
+
class Gene_Braintree_Model_Source_Paypal_Locale
|
8 |
+
{
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Return the array of options
|
12 |
+
* @return array
|
13 |
+
*/
|
14 |
+
public function getArray()
|
15 |
+
{
|
16 |
+
return array(
|
17 |
+
'en_au' => Mage::helper('gene_braintree')->__('Australia'),
|
18 |
+
'en_ca' => Mage::helper('gene_braintree')->__('Canada'),
|
19 |
+
'fr_fr' => Mage::helper('gene_braintree')->__('France'),
|
20 |
+
'de_de' => Mage::helper('gene_braintree')->__('Germany'),
|
21 |
+
'en_gb' => Mage::helper('gene_braintree')->__('Great Britain & Ireland'),
|
22 |
+
'zh_hk' => Mage::helper('gene_braintree')->__('Hong Kong'),
|
23 |
+
'it_it' => Mage::helper('gene_braintree')->__('Italy'),
|
24 |
+
'es_es' => Mage::helper('gene_braintree')->__('Spain'),
|
25 |
+
'en_us' => Mage::helper('gene_braintree')->__('United States')
|
26 |
+
);
|
27 |
+
}
|
28 |
+
/**
|
29 |
+
* Options getter
|
30 |
+
*
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
public function toOptionArray()
|
34 |
+
{
|
35 |
+
$response = array();
|
36 |
+
foreach($this->getArray() as $key => $value) {
|
37 |
+
$response[] = array(
|
38 |
+
'value' => $key,
|
39 |
+
'label' => $value
|
40 |
+
);
|
41 |
+
}
|
42 |
+
return $response;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Get options in "key-value" format
|
47 |
+
*
|
48 |
+
* @return array
|
49 |
+
*/
|
50 |
+
public function toArray()
|
51 |
+
{
|
52 |
+
return $this->getArray();
|
53 |
+
}
|
54 |
+
|
55 |
+
}
|
app/code/community/Gene/Braintree/Model/Source/Paypal/Paymenttype.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Source_Paypal_Paymenttype
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Source_Paypal_Paymenttype
|
9 |
+
{
|
10 |
+
|
11 |
+
const GENE_BRAINTREE_PAYPAL_SINGLE_PAYMENT = 'single';
|
12 |
+
const GENE_BRAINTREE_PAYPAL_FUTURE_PAYMENTS = 'future';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Return our options
|
16 |
+
*
|
17 |
+
* @return array
|
18 |
+
*/
|
19 |
+
public function toOptionArray()
|
20 |
+
{
|
21 |
+
return array(
|
22 |
+
array(
|
23 |
+
'value' => self::GENE_BRAINTREE_PAYPAL_SINGLE_PAYMENT,
|
24 |
+
'label' => Mage::helper('gene_braintree')->__('Single Payment'),
|
25 |
+
),
|
26 |
+
array(
|
27 |
+
'value' => self::GENE_BRAINTREE_PAYPAL_FUTURE_PAYMENTS,
|
28 |
+
'label' => Mage::helper('gene_braintree')->__('Future Payments')
|
29 |
+
)
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
}
|
app/code/community/Gene/Braintree/Model/System/Config/Backend/Currency.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_System_Config_Backend_Currency
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_System_Config_Backend_Currency extends Mage_Core_Model_Config_Data
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Json decode the value
|
13 |
+
*/
|
14 |
+
protected function _afterLoad()
|
15 |
+
{
|
16 |
+
if (!is_array($this->getValue())) {
|
17 |
+
$value = $this->getValue();
|
18 |
+
$this->setValue(empty($value) ? false : json_decode($value));
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Json encode the value to be stored in the database
|
24 |
+
*/
|
25 |
+
protected function _beforeSave()
|
26 |
+
{
|
27 |
+
if (is_array($this->getValue())) {
|
28 |
+
$this->setValue(json_encode($this->getValue()));
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
}
|
app/code/community/Gene/Braintree/Model/Wrapper/Braintree.php
ADDED
@@ -0,0 +1,729 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Model_Wrapper_Braintree
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Model_Wrapper_Braintree extends Mage_Core_Model_Abstract
|
9 |
+
{
|
10 |
+
|
11 |
+
CONST BRAINTREE_ENVIRONMENT_PATH = 'payment/gene_braintree/environment';
|
12 |
+
CONST BRAINTREE_MERCHANT_ID_PATH = 'payment/gene_braintree/merchant_id';
|
13 |
+
CONST BRAINTREE_MERCHANT_ACCOUNT_ID_PATH = 'payment/gene_braintree/merchant_account_id';
|
14 |
+
CONST BRAINTREE_PUBLIC_KEY_PATH = 'payment/gene_braintree/public_key';
|
15 |
+
CONST BRAINTREE_PRIVATE_KEY_PATH = 'payment/gene_braintree/private_key';
|
16 |
+
|
17 |
+
const BRAINTREE_MULTI_CURRENCY = 'payment/gene_braintree/multi_currency_enable';
|
18 |
+
const BRAINTREE_MULTI_CURRENCY_MAPPING = 'payment/gene_braintree/multi_currency_mapping';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Store the customer
|
22 |
+
*
|
23 |
+
* @var Braintree_Customer
|
24 |
+
*/
|
25 |
+
private $customer;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Store the Braintree ID
|
29 |
+
*
|
30 |
+
* @var int
|
31 |
+
*/
|
32 |
+
private $braintreeId;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Used to track whether the payment methods are available
|
36 |
+
*
|
37 |
+
* @var bool
|
38 |
+
*/
|
39 |
+
private $validated = null;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* If we're using a mapped currency we need to charge the grand total, instead of the base
|
43 |
+
*
|
44 |
+
* @var bool
|
45 |
+
*/
|
46 |
+
private $mappedCurrency = false;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Store whether or not we've init the environment yet
|
50 |
+
*
|
51 |
+
* @var bool
|
52 |
+
*/
|
53 |
+
private $init = false;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Setup the environment
|
57 |
+
*
|
58 |
+
* @return $this
|
59 |
+
*/
|
60 |
+
public function init($store = null)
|
61 |
+
{
|
62 |
+
if(!$this->init) {
|
63 |
+
|
64 |
+
// Setup the various configuration variables
|
65 |
+
Braintree_Configuration::environment(Mage::getStoreConfig(self::BRAINTREE_ENVIRONMENT_PATH, $store));
|
66 |
+
Braintree_Configuration::merchantId(Mage::getStoreConfig(self::BRAINTREE_MERCHANT_ID_PATH, $store));
|
67 |
+
Braintree_Configuration::publicKey(Mage::getStoreConfig(self::BRAINTREE_PUBLIC_KEY_PATH, $store));
|
68 |
+
Braintree_Configuration::privateKey(Mage::getStoreConfig(self::BRAINTREE_PRIVATE_KEY_PATH, $store));
|
69 |
+
|
70 |
+
// Set our flag
|
71 |
+
$this->init = true;
|
72 |
+
}
|
73 |
+
|
74 |
+
return $this;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Find a transaction
|
79 |
+
*
|
80 |
+
* @param $transactionId
|
81 |
+
*
|
82 |
+
* @throws Braintree_Exception_NotFound
|
83 |
+
*/
|
84 |
+
public function findTransaction($transactionId)
|
85 |
+
{
|
86 |
+
return Braintree_Transaction::find($transactionId);
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* If we're trying to charge a 3D secure card in the vault we need to build a special nonce
|
91 |
+
*
|
92 |
+
* @param $paymentMethodToken
|
93 |
+
*
|
94 |
+
* @return mixed
|
95 |
+
*/
|
96 |
+
public function getThreeDSecureVaultNonce($paymentMethodToken)
|
97 |
+
{
|
98 |
+
$this->init();
|
99 |
+
|
100 |
+
$result = Braintree_PaymentMethodNonce::create($paymentMethodToken);
|
101 |
+
return $result->paymentMethodNonce->nonce;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Try and load the Braintree customer from the stored customer ID
|
106 |
+
*
|
107 |
+
* @param $braintreeCustomerId
|
108 |
+
*
|
109 |
+
* @return Braintree_Customer
|
110 |
+
*/
|
111 |
+
public function getCustomer($braintreeCustomerId)
|
112 |
+
{
|
113 |
+
// Try and load it from the customer
|
114 |
+
if(!$this->customer && !isset($this->customer[$braintreeCustomerId])) {
|
115 |
+
try {
|
116 |
+
$this->customer[$braintreeCustomerId] = Braintree_Customer::find($braintreeCustomerId);
|
117 |
+
} catch (Exception $e) {
|
118 |
+
return false;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this->customer[$braintreeCustomerId];
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Check to see whether this customer already exists
|
127 |
+
*
|
128 |
+
* @return bool|object
|
129 |
+
*/
|
130 |
+
public function checkIsCustomer()
|
131 |
+
{
|
132 |
+
try {
|
133 |
+
// Check to see that we can generate a braintree ID
|
134 |
+
if($braintreeId = $this->getBraintreeId()) {
|
135 |
+
|
136 |
+
// Proxy this request to the other method which has caching
|
137 |
+
return $this->getCustomer($braintreeId);
|
138 |
+
}
|
139 |
+
} catch (Exception $e) {
|
140 |
+
return false;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Generate a server side token with the specified account ID
|
146 |
+
*
|
147 |
+
* @return mixed
|
148 |
+
*/
|
149 |
+
public function generateToken()
|
150 |
+
{
|
151 |
+
// Use the class to generate the token
|
152 |
+
return Braintree_ClientToken::generate();
|
153 |
+
}
|
154 |
+
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Check a customer owns the method we're trying to modify
|
158 |
+
*
|
159 |
+
* @param $paymentMethod
|
160 |
+
*
|
161 |
+
* @return bool
|
162 |
+
*/
|
163 |
+
public function customerOwnsMethod($paymentMethod)
|
164 |
+
{
|
165 |
+
// Grab the customer ID from the customers account
|
166 |
+
$customerId = Mage::getSingleton('customer/session')->getCustomer()->getBraintreeCustomerId();
|
167 |
+
|
168 |
+
// Detect which type of payment method we've got here
|
169 |
+
if($paymentMethod instanceof Braintree_PayPalAccount) {
|
170 |
+
|
171 |
+
// Grab the customer
|
172 |
+
$customer = $this->getCustomer($customerId);
|
173 |
+
|
174 |
+
// Store all the tokens in an array
|
175 |
+
$customerTokens = array();
|
176 |
+
|
177 |
+
// Check the customer has PayPal Accounts
|
178 |
+
if(isset($customer->paypalAccounts)) {
|
179 |
+
|
180 |
+
/* @var $payPalAccount Braintree_PayPalAccount */
|
181 |
+
foreach($customer->paypalAccounts as $payPalAccount) {
|
182 |
+
if(isset($payPalAccount->token)) {
|
183 |
+
$customerTokens[] = $payPalAccount->token;
|
184 |
+
}
|
185 |
+
}
|
186 |
+
} else {
|
187 |
+
return false;
|
188 |
+
}
|
189 |
+
|
190 |
+
// Check to see if this customer account contains this token
|
191 |
+
if(in_array($paymentMethod->token, $customerTokens)) {
|
192 |
+
return true;
|
193 |
+
}
|
194 |
+
|
195 |
+
return false;
|
196 |
+
|
197 |
+
} else if(isset($paymentMethod->customerId) && $paymentMethod->customerId == $customerId) {
|
198 |
+
|
199 |
+
return true;
|
200 |
+
}
|
201 |
+
|
202 |
+
return false;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Retrieve the Braintree ID from Magento
|
207 |
+
*
|
208 |
+
* @return bool|string
|
209 |
+
*/
|
210 |
+
protected function getBraintreeId()
|
211 |
+
{
|
212 |
+
// Some basic caching
|
213 |
+
if(!$this->braintreeId) {
|
214 |
+
|
215 |
+
// Is the customer already logged in
|
216 |
+
if (Mage::getSingleton('customer/session')->isLoggedIn()) {
|
217 |
+
|
218 |
+
// Retrieve the current customer
|
219 |
+
$customer = Mage::getSingleton('customer/session')->getCustomer();
|
220 |
+
|
221 |
+
// Determine whether they have a braintree customer ID already
|
222 |
+
if ($brainteeId = $customer->getBraintreeCustomerId()) {
|
223 |
+
$this->braintreeId = $customer->getBraintreeCustomerId();
|
224 |
+
} else {
|
225 |
+
// If not let's create them one
|
226 |
+
$this->braintreeId = $this->buildCustomerId();
|
227 |
+
$customer->setBraintreeCustomerId($this->braintreeId)->save();
|
228 |
+
}
|
229 |
+
|
230 |
+
} else {
|
231 |
+
if ((Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == 'login_in' || Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER)) {
|
232 |
+
|
233 |
+
// Check to see if we've already generated an ID
|
234 |
+
if($braintreeId = Mage::getSingleton('checkout/session')->getBraintreeCustomerId()) {
|
235 |
+
$this->braintreeId = $braintreeId;
|
236 |
+
} else {
|
237 |
+
// If the user plans to register let's build them an ID and store it in their session
|
238 |
+
$this->braintreeId = $this->buildCustomerId();
|
239 |
+
Mage::getSingleton('checkout/session')->setBraintreeCustomerId($this->braintreeId);
|
240 |
+
}
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
}
|
245 |
+
|
246 |
+
return $this->braintreeId;
|
247 |
+
}
|
248 |
+
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Validate the credentials within the admin area
|
252 |
+
*
|
253 |
+
* @return bool
|
254 |
+
*/
|
255 |
+
public function validateCredentials($prettyResponse = false, $alreadyInit = false, $merchantAccountId = false)
|
256 |
+
{
|
257 |
+
// Try to init the environment
|
258 |
+
try {
|
259 |
+
if(!$alreadyInit) {
|
260 |
+
|
261 |
+
// If we're within the admin we want to grab these values from whichever store we're modifying
|
262 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
263 |
+
Braintree_Configuration::environment(Mage::getSingleton('adminhtml/config_data')->getConfigDataValue(self::BRAINTREE_ENVIRONMENT_PATH));
|
264 |
+
Braintree_Configuration::merchantId(Mage::getSingleton('adminhtml/config_data')->getConfigDataValue(self::BRAINTREE_MERCHANT_ID_PATH));
|
265 |
+
Braintree_Configuration::publicKey(Mage::getSingleton('adminhtml/config_data')->getConfigDataValue(self::BRAINTREE_PUBLIC_KEY_PATH));
|
266 |
+
Braintree_Configuration::privateKey(Mage::getSingleton('adminhtml/config_data')->getConfigDataValue(self::BRAINTREE_PRIVATE_KEY_PATH));
|
267 |
+
} else {
|
268 |
+
$this->init();
|
269 |
+
}
|
270 |
+
}
|
271 |
+
} catch (Exception $e) {
|
272 |
+
|
273 |
+
if($prettyResponse) {
|
274 |
+
return '<span style="color: red;font-weight: bold;" id="braintree-valid-config">' . Mage::helper('gene_braintree')->__('Invalid Credentials') . '</span><br />' . Mage::helper('gene_braintree')->__('Payments cannot be processed until this is resolved, due to this the methods will be hidden within the checkout');
|
275 |
+
}
|
276 |
+
return false;
|
277 |
+
}
|
278 |
+
|
279 |
+
// Check to see if we've been passed the merchant account ID?
|
280 |
+
if(!$merchantAccountId) {
|
281 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
282 |
+
$merchantAccountId = Mage::getSingleton('adminhtml/config_data')->getConfigDataValue(self::BRAINTREE_MERCHANT_ACCOUNT_ID_PATH);
|
283 |
+
} else {
|
284 |
+
$merchantAccountId = $this->getMerchantAccountId();
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
// Validate the merchant account ID
|
289 |
+
try {
|
290 |
+
Braintree_Configuration::gateway()->merchantAccount()->find($merchantAccountId);
|
291 |
+
} catch (Exception $e) {
|
292 |
+
if($prettyResponse) {
|
293 |
+
return '<span style="color: orange;font-weight: bold;" id="braintree-valid-config">' . Mage::helper('gene_braintree')->__('Invalid Merchant Account ID') . '</span><br />' . Mage::helper('gene_braintree')->__('Payments cannot be processed until this is resolved. We cannot find your merchant account ID associated with the other credentials you\'ve provided, please update this field');
|
294 |
+
}
|
295 |
+
return false;
|
296 |
+
}
|
297 |
+
|
298 |
+
if($prettyResponse) {
|
299 |
+
return '<span style="color: green;font-weight: bold;" id="braintree-valid-config">' . Mage::helper('gene_braintree')->__('Valid Credentials') . '</span><br />' . Mage::helper('gene_braintree')->__('You\'re ready to accept payments via Braintree');
|
300 |
+
}
|
301 |
+
return true;
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Validate the credentials once, this is used during the payment methods available check
|
306 |
+
* @return bool
|
307 |
+
*/
|
308 |
+
public function validateCredentialsOnce()
|
309 |
+
{
|
310 |
+
// Check to see if it's been validated yet
|
311 |
+
if(is_null($this->validated)) {
|
312 |
+
|
313 |
+
// Check the Braintree lib version is above 2.32, as this is when 3D secure appeared
|
314 |
+
if (Braintree_Version::get() < 2.32) {
|
315 |
+
$this->validated = false;
|
316 |
+
} else {
|
317 |
+
|
318 |
+
// Check that the module is fully setup
|
319 |
+
if (!Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_ENVIRONMENT_PATH)
|
320 |
+
|| !Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_MERCHANT_ID_PATH)
|
321 |
+
|| !Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_PUBLIC_KEY_PATH)
|
322 |
+
|| !Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_PRIVATE_KEY_PATH)
|
323 |
+
) {
|
324 |
+
// If not the payment methods aren't available
|
325 |
+
$this->validated = false;
|
326 |
+
|
327 |
+
} else {
|
328 |
+
|
329 |
+
// Try and validate the stored credentials
|
330 |
+
if (!Mage::getModel('gene_braintree/wrapper_braintree')->validateCredentials()) {
|
331 |
+
|
332 |
+
// Only add this in if it's not the last notice
|
333 |
+
$latestNotice = Mage::getModel('adminnotification/inbox')->loadLatestNotice();
|
334 |
+
|
335 |
+
// Validate there is a latest notice
|
336 |
+
if ($latestNotice && $latestNotice->getId()) {
|
337 |
+
|
338 |
+
// Check to see if the title contains our error
|
339 |
+
// Magento does not provide a nice way of doing this that I'm aware of
|
340 |
+
if (strpos($latestNotice->getTitle(), 'Braintree Configuration Invalid') === false) {
|
341 |
+
|
342 |
+
// If it doesn't add it again!
|
343 |
+
Mage::getModel('adminnotification/inbox')->addMajor(Mage::helper('gene_braintree')->__('Braintree Configuration Invalid - %s - This could be stopping payments', Mage::app()->getStore()->getFrontendName()), Mage::helper('gene_braintree')->__('The configuration values in the Magento Braintree v.zero module are incorrect, until these values are corrected the system can not function. This occurred on store %s - ID: %s', Mage::app()->getStore()->getFrontendName(), Mage::app()->getStore()->getId()));
|
344 |
+
}
|
345 |
+
|
346 |
+
} else {
|
347 |
+
|
348 |
+
// Otherwise there hasn't been any other notices
|
349 |
+
Mage::getModel('adminnotification/inbox')->addMajor(Mage::helper('gene_braintree')->__('Braintree Configuration Invalid - %s - This could be stopping payments', Mage::app()->getStore()->getFrontendName()), Mage::helper('gene_braintree')->__('The configuration values in the Magento Braintree v.zero module are incorrect, until these values are corrected the system can not function. This occurred on store %s - ID: %s', Mage::app()->getStore()->getFrontendName(), Mage::app()->getStore()->getId()));
|
350 |
+
}
|
351 |
+
|
352 |
+
$this->validated = false;
|
353 |
+
|
354 |
+
} else {
|
355 |
+
|
356 |
+
// Otherwise the method validated
|
357 |
+
$this->validated = true;
|
358 |
+
}
|
359 |
+
}
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
return $this->validated;
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* Build up the sale request
|
368 |
+
*
|
369 |
+
* @param $amount
|
370 |
+
* @param array $paymentDataArray
|
371 |
+
* @param Mage_Sales_Model_Order $order
|
372 |
+
* @param bool $submitForSettlement
|
373 |
+
* @param bool $deviceData
|
374 |
+
* @param bool $storeInVault
|
375 |
+
* @param bool $threeDSecure
|
376 |
+
* @param array $extra
|
377 |
+
*
|
378 |
+
* @return array
|
379 |
+
*
|
380 |
+
* @throws Mage_Core_Exception
|
381 |
+
*/
|
382 |
+
public function buildSale(
|
383 |
+
$amount,
|
384 |
+
array $paymentDataArray,
|
385 |
+
Mage_Sales_Model_Order $order,
|
386 |
+
$submitForSettlement = true,
|
387 |
+
$deviceData = false,
|
388 |
+
$storeInVault = false,
|
389 |
+
$threeDSecure = false,
|
390 |
+
$extra = array()
|
391 |
+
) {
|
392 |
+
// Check we always have an ID
|
393 |
+
if (!$order->getIncrementId()) {
|
394 |
+
Mage::throwException('Your order has become invalid, please try refreshing.');
|
395 |
+
}
|
396 |
+
|
397 |
+
// Store whether or not we created a new method
|
398 |
+
$createdMethod = false;
|
399 |
+
|
400 |
+
// If the user is already a customer and wants to store in the vault we've gotta do something a bit special
|
401 |
+
if($storeInVault && $this->checkIsCustomer() && isset($paymentDataArray['paymentMethodNonce'])) {
|
402 |
+
|
403 |
+
// Create the payment method with this data
|
404 |
+
$paymentMethodCreate = array(
|
405 |
+
'customerId' => $this->getBraintreeId(),
|
406 |
+
'paymentMethodNonce' => $paymentDataArray['paymentMethodNonce'],
|
407 |
+
'billingAddress' => $this->buildAddress($order->getBillingAddress())
|
408 |
+
);
|
409 |
+
|
410 |
+
// Log the create array
|
411 |
+
Gene_Braintree_Model_Debug::log(array('Braintree_PaymentMethod' => $paymentMethodCreate));
|
412 |
+
|
413 |
+
// Create a new billing method
|
414 |
+
$result = Braintree_PaymentMethod::create($paymentMethodCreate);
|
415 |
+
|
416 |
+
// Log the response from Braintree
|
417 |
+
Gene_Braintree_Model_Debug::log(array('Braintree_PaymentMethod:result' => $paymentMethodCreate));
|
418 |
+
|
419 |
+
// Verify the storing of the card was a success
|
420 |
+
if(isset($result->success) && $result->success == true) {
|
421 |
+
|
422 |
+
/* @var $paymentMethod Braintree_CreditCard */
|
423 |
+
$paymentMethod = $result->paymentMethod;
|
424 |
+
|
425 |
+
// Check to see if the token is set
|
426 |
+
if(isset($paymentMethod->token) && !empty($paymentMethod->token)) {
|
427 |
+
|
428 |
+
// We no longer need this nonce
|
429 |
+
unset($paymentDataArray['paymentMethodNonce']);
|
430 |
+
|
431 |
+
// Instead use the token
|
432 |
+
$paymentDataArray['paymentMethodToken'] = $paymentMethod->token;
|
433 |
+
|
434 |
+
// Create a flag for other methods
|
435 |
+
$createdMethod = true;
|
436 |
+
}
|
437 |
+
|
438 |
+
} else {
|
439 |
+
Mage::throwException($result->message . Mage::helper('gene_braintree')->__(' Please try again or attempt refreshing the page.'));
|
440 |
+
}
|
441 |
+
}
|
442 |
+
|
443 |
+
// Build up the initial request parameters
|
444 |
+
$request = array(
|
445 |
+
'amount' => $amount,
|
446 |
+
'orderId' => $order->getIncrementId(),
|
447 |
+
'merchantAccountId' => $this->getMerchantAccountId(),
|
448 |
+
'channel' => 'MagentoVZero',
|
449 |
+
'options' => array(
|
450 |
+
'submitForSettlement' => $submitForSettlement,
|
451 |
+
'storeInVault' => $storeInVault
|
452 |
+
)
|
453 |
+
);
|
454 |
+
|
455 |
+
// Input the allowed payment method info
|
456 |
+
$allowedPaymentInfo = array('paymentMethodNonce','paymentMethodToken','token','cvv');
|
457 |
+
foreach($paymentDataArray as $key => $value) {
|
458 |
+
if(in_array($key, $allowedPaymentInfo)) {
|
459 |
+
if($key == 'cvv') {
|
460 |
+
$request['creditCard']['cvv'] = $value;
|
461 |
+
} else {
|
462 |
+
$request[$key] = $value;
|
463 |
+
}
|
464 |
+
} else {
|
465 |
+
Mage::throwException($key.' is not allowed within $paymentDataArray');
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
// Include the customer if we're creating a new one
|
470 |
+
if(!$this->checkIsCustomer() && (Mage::getSingleton('customer/session')->isLoggedIn() ||
|
471 |
+
(Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == 'login_in' || Mage::getSingleton('checkout/type_onepage')->getCheckoutMethod() == Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER))) {
|
472 |
+
$request['customer'] = $this->buildCustomer($order);
|
473 |
+
} else {
|
474 |
+
// If the customer exists but we aren't using the vault we want to pass a customer object with no ID
|
475 |
+
$request['customer'] = $this->buildCustomer($order, false);
|
476 |
+
}
|
477 |
+
|
478 |
+
// Do we have any deviceData to send over?
|
479 |
+
if ($deviceData) {
|
480 |
+
$request['deviceData'] = $deviceData;
|
481 |
+
}
|
482 |
+
|
483 |
+
// Include the shipping address
|
484 |
+
if ($order->getShippingAddress()) {
|
485 |
+
$request['shipping'] = $this->buildAddress($order->getShippingAddress());
|
486 |
+
}
|
487 |
+
|
488 |
+
// Include the billing address
|
489 |
+
if ($order->getBillingAddress()) {
|
490 |
+
$request['billing'] = $this->buildAddress($order->getBillingAddress());
|
491 |
+
}
|
492 |
+
|
493 |
+
// Is 3D secure enabled?
|
494 |
+
if($threeDSecure !== false && !$createdMethod) {
|
495 |
+
$request['options']['three_d_secure']['required'] = true;
|
496 |
+
}
|
497 |
+
|
498 |
+
// Any extra information we want to supply
|
499 |
+
if(!empty($extra) && is_array($extra)) {
|
500 |
+
$request = array_merge($request, $extra);
|
501 |
+
}
|
502 |
+
|
503 |
+
return $request;
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Attempt to make the sale
|
508 |
+
*
|
509 |
+
* @param $saleArray
|
510 |
+
*
|
511 |
+
* @return stdClass
|
512 |
+
*/
|
513 |
+
public function makeSale($saleArray)
|
514 |
+
{
|
515 |
+
// Call the braintree library
|
516 |
+
return Braintree_Transaction::sale(
|
517 |
+
$saleArray
|
518 |
+
);
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* Submit a payment for settlement
|
523 |
+
*
|
524 |
+
* @param $transactionId
|
525 |
+
* @param $amount
|
526 |
+
*
|
527 |
+
* @throws Mage_Core_Exception
|
528 |
+
*/
|
529 |
+
public function submitForSettlement($transactionId, $amount)
|
530 |
+
{
|
531 |
+
// Attempt to submit for settlement
|
532 |
+
$result = Braintree_Transaction::submitForSettlement($transactionId, $amount);
|
533 |
+
|
534 |
+
return $result;
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Build the customers ID, md5 a uniquid
|
539 |
+
*
|
540 |
+
* @param Mage_Sales_Model_Order $order
|
541 |
+
*
|
542 |
+
* @return string
|
543 |
+
* @throws Mage_Core_Exception
|
544 |
+
*/
|
545 |
+
private function buildCustomerId()
|
546 |
+
{
|
547 |
+
return md5(uniqid('braintree_',true));
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Build a Magento address model into a Braintree array
|
552 |
+
*
|
553 |
+
* @param Mage_Sales_Model_Order_Address $address
|
554 |
+
*
|
555 |
+
* @return array
|
556 |
+
*/
|
557 |
+
private function buildAddress(Mage_Sales_Model_Order_Address $address)
|
558 |
+
{
|
559 |
+
// Build up the initial array
|
560 |
+
$return = array(
|
561 |
+
'firstName' => $address->getFirstname(),
|
562 |
+
'lastName' => $address->getLastname(),
|
563 |
+
'streetAddress' => $address->getStreet1(),
|
564 |
+
'locality' => $address->getCity(),
|
565 |
+
'postalCode' => $address->getPostcode(),
|
566 |
+
'countryCodeAlpha2' => $address->getCountry()
|
567 |
+
);
|
568 |
+
|
569 |
+
// Any extended address?
|
570 |
+
if ($address->getStreet2()) {
|
571 |
+
$return['extendedAddress'] = $address->getStreet2();
|
572 |
+
}
|
573 |
+
|
574 |
+
// Region
|
575 |
+
if ($address->getRegion()) {
|
576 |
+
$return['region'] = $address->getRegionCode();
|
577 |
+
}
|
578 |
+
|
579 |
+
// Check to see if we have a company
|
580 |
+
if ($address->getCompany()) {
|
581 |
+
$return['company'] = $address->getCompany();
|
582 |
+
}
|
583 |
+
|
584 |
+
return $return;
|
585 |
+
}
|
586 |
+
|
587 |
+
/**
|
588 |
+
* Return the correct merchant account ID
|
589 |
+
*
|
590 |
+
* @return mixed
|
591 |
+
*/
|
592 |
+
public function getMerchantAccountId()
|
593 |
+
{
|
594 |
+
// If multi-currency is enabled use the mapped merchant account ID
|
595 |
+
if($currencyCode = $this->hasMappedCurrencyCode()) {
|
596 |
+
|
597 |
+
// Return the mapped currency code
|
598 |
+
return $currencyCode;
|
599 |
+
}
|
600 |
+
|
601 |
+
// Otherwise return the one from the store
|
602 |
+
return Mage::getStoreConfig(self::BRAINTREE_MERCHANT_ACCOUNT_ID_PATH);
|
603 |
+
}
|
604 |
+
|
605 |
+
/**
|
606 |
+
* If we have a mapped currency code reutrn it
|
607 |
+
*
|
608 |
+
* @return bool
|
609 |
+
*/
|
610 |
+
public function hasMappedCurrencyCode()
|
611 |
+
{
|
612 |
+
// If multi-currency is enabled use the mapped merchant account ID
|
613 |
+
if($this->currencyMappingEnabled()) {
|
614 |
+
|
615 |
+
// Retrieve the mapping from the config
|
616 |
+
$mapping = Mage::helper('core')->jsonDecode(Mage::getStoreConfig(self::BRAINTREE_MULTI_CURRENCY_MAPPING));
|
617 |
+
|
618 |
+
// Verify it decoded correctly
|
619 |
+
if(is_array($mapping) && !empty($mapping)) {
|
620 |
+
|
621 |
+
// If we're in the admin get the currency code from the admin session quote
|
622 |
+
if(Mage::app()->getStore()->isAdmin()) {
|
623 |
+
$currency = $this->getAdminCurrency();
|
624 |
+
} else {
|
625 |
+
// Retrieve the current from the session
|
626 |
+
$currency = Mage::app()->getStore()->getCurrentCurrencyCode();
|
627 |
+
}
|
628 |
+
|
629 |
+
// Verify we have a mapping value for this currency
|
630 |
+
if(isset($mapping[$currency]) && !empty($mapping[$currency])) {
|
631 |
+
|
632 |
+
return $mapping[$currency];
|
633 |
+
}
|
634 |
+
}
|
635 |
+
}
|
636 |
+
|
637 |
+
return false;
|
638 |
+
}
|
639 |
+
|
640 |
+
/**
|
641 |
+
* Do we have currency mapping enabled?
|
642 |
+
*
|
643 |
+
* @return bool
|
644 |
+
*/
|
645 |
+
public function currencyMappingEnabled()
|
646 |
+
{
|
647 |
+
return Mage::getStoreConfigFlag(self::BRAINTREE_MULTI_CURRENCY)
|
648 |
+
&& Mage::getStoreConfig(self::BRAINTREE_MULTI_CURRENCY_MAPPING)
|
649 |
+
&& (Mage::app()->getStore()->getCurrentCurrencyCode() || (Mage::app()->getStore()->isAdmin() && $this->getAdminCurrency()));
|
650 |
+
}
|
651 |
+
|
652 |
+
/**
|
653 |
+
* If we have a mapped currency code we need to convert the currency
|
654 |
+
*
|
655 |
+
* @param $amount
|
656 |
+
*
|
657 |
+
* @return mixed
|
658 |
+
*/
|
659 |
+
public function getCaptureAmount(Mage_Sales_Model_Order $order, $amount)
|
660 |
+
{
|
661 |
+
// If we've got a mapped currency code the amount is going to change
|
662 |
+
if($currencyCode = $this->hasMappedCurrencyCode()) {
|
663 |
+
|
664 |
+
// Convert the current
|
665 |
+
$convertedCurrency = Mage::helper('directory')->currencyConvert($amount, $order->getBaseCurrencyCode(), $currencyCode);
|
666 |
+
|
667 |
+
// Format it to a precision of 2
|
668 |
+
$options = array(
|
669 |
+
'currency' => $currencyCode,
|
670 |
+
'display' => ''
|
671 |
+
);
|
672 |
+
|
673 |
+
return Mage::app()->getLocale()->currency($currencyCode)->toCurrency($convertedCurrency, $options);
|
674 |
+
}
|
675 |
+
|
676 |
+
return $amount;
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* Retrieve the admin currency
|
681 |
+
*
|
682 |
+
* @return bool
|
683 |
+
*/
|
684 |
+
private function getAdminCurrency()
|
685 |
+
{
|
686 |
+
$order = Mage::app()->getRequest()->getPost('order');
|
687 |
+
if(isset($order['currency']) && !empty($order['currency'])) {
|
688 |
+
return $order['currency'];
|
689 |
+
}
|
690 |
+
|
691 |
+
return false;
|
692 |
+
}
|
693 |
+
|
694 |
+
/**
|
695 |
+
* Build up the customers data onto an object
|
696 |
+
*
|
697 |
+
* @param Mage_Sales_Model_Order $order
|
698 |
+
*
|
699 |
+
* @return array
|
700 |
+
*/
|
701 |
+
private function buildCustomer(Mage_Sales_Model_Order $order, $includeId = true)
|
702 |
+
{
|
703 |
+
$customer = array(
|
704 |
+
'firstName' => $order->getCustomerFirstname(),
|
705 |
+
'lastName' => $order->getCustomerLastname(),
|
706 |
+
'email' => $order->getCustomerEmail(),
|
707 |
+
'phone' => $order->getBillingAddress()->getTelephone()
|
708 |
+
);
|
709 |
+
|
710 |
+
// Shall we include the customer ID?
|
711 |
+
if($includeId) {
|
712 |
+
$customer['id'] = $this->getBraintreeId();
|
713 |
+
}
|
714 |
+
|
715 |
+
// Handle empty data with alternatives
|
716 |
+
if(empty($customer['firstName'])) {
|
717 |
+
$customer['firstName'] = $order->getBillingAddress()->getFirstname();
|
718 |
+
}
|
719 |
+
if(empty($customer['lastName'])) {
|
720 |
+
$customer['lastName'] = $order->getBillingAddress()->getLastname();
|
721 |
+
}
|
722 |
+
if(empty($customer['email'])) {
|
723 |
+
$customer['email'] = $order->getBillingAddress()->getEmail();
|
724 |
+
}
|
725 |
+
|
726 |
+
return $customer;
|
727 |
+
}
|
728 |
+
|
729 |
+
}
|
app/code/community/Gene/Braintree/controllers/Adminhtml/BraintreeController.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_Adminhtml_BraintreeController
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_Adminhtml_BraintreeController extends Mage_Adminhtml_Controller_Action
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Settlement report from Braintree
|
13 |
+
*/
|
14 |
+
public function transactionsAction()
|
15 |
+
{
|
16 |
+
$this->loadLayout();
|
17 |
+
|
18 |
+
$this->_title(Mage::helper('gene_braintree')->__('Braintree Transactions'));
|
19 |
+
$this->_setActiveMenu('report/braintree_transactions');
|
20 |
+
|
21 |
+
$this->renderLayout();
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Prepare the export into the browser
|
26 |
+
*
|
27 |
+
* @param string $type
|
28 |
+
*
|
29 |
+
* @return bool
|
30 |
+
*/
|
31 |
+
private function _prepareExport($type = 'csv')
|
32 |
+
{
|
33 |
+
// Validate the search query session is set
|
34 |
+
if($searchQuery = Mage::getSingleton('adminhtml/session')->getBraintreeSearchQuery()) {
|
35 |
+
|
36 |
+
// Grab the grid block
|
37 |
+
$grid = $this->getLayout()->createBlock('gene_braintree/adminhtml_report_transactions_grid');
|
38 |
+
|
39 |
+
// Set the search query within the grid
|
40 |
+
$grid->setSearchQuery($searchQuery);
|
41 |
+
|
42 |
+
// Force the file to download in the browser
|
43 |
+
$this->_prepareDownloadResponse('braintree-transactions.' . $type, ($type == 'xml' ? $grid->getExcelFile() : $grid->getCsvFile()));
|
44 |
+
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
|
48 |
+
// Otherwise take them back
|
49 |
+
$this->_redirectReferer();
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Process a request to export the current transactions to a CSV
|
54 |
+
*/
|
55 |
+
public function exportCsvAction()
|
56 |
+
{
|
57 |
+
return $this->_prepareExport('csv');
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Process a request to export the current transaction to an Excel Document
|
62 |
+
*/
|
63 |
+
public function exportExcelAction()
|
64 |
+
{
|
65 |
+
return $this->_prepareExport('xml');
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Validate the inputted configuration via Ajax
|
70 |
+
*/
|
71 |
+
public function validateConfigAction()
|
72 |
+
{
|
73 |
+
// Grab the post data from the request
|
74 |
+
$postData = Mage::app()->getRequest()->getPost();
|
75 |
+
|
76 |
+
// Check the form contains the valid data we need
|
77 |
+
if(isset($postData['groups']['gene_braintree']['fields'])) {
|
78 |
+
|
79 |
+
// Assign it for easy access
|
80 |
+
$braintreeConfig = $postData['groups']['gene_braintree']['fields'];
|
81 |
+
|
82 |
+
// Validate the required variables are set before trying to access them
|
83 |
+
if(isset($braintreeConfig['environment']) && isset($braintreeConfig['merchant_id']) && isset($braintreeConfig['public_key']) && isset($braintreeConfig['private_key'])) {
|
84 |
+
|
85 |
+
// Setup the various configuration variables
|
86 |
+
Braintree_Configuration::environment($braintreeConfig['environment']['value']);
|
87 |
+
Braintree_Configuration::merchantId($braintreeConfig['merchant_id']['value']);
|
88 |
+
Braintree_Configuration::publicKey($braintreeConfig['public_key']['value']);
|
89 |
+
Braintree_Configuration::privateKey($braintreeConfig['private_key']['value']);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
// Do the validation within the wrapper
|
94 |
+
Mage::app()->getResponse()->setBody(Mage::getModel('gene_braintree/wrapper_braintree')->validateCredentials(true, true, (isset($braintreeConfig['merchant_account_id']['value']) ? $braintreeConfig['merchant_account_id']['value'] : false)));
|
95 |
+
}
|
96 |
+
|
97 |
+
}
|
app/code/community/Gene/Braintree/controllers/CheckoutController.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_CheckoutController
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_CheckoutController extends Mage_Core_Controller_Front_Action
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* The front-end is requesting the grand total of the quote
|
12 |
+
*/
|
13 |
+
public function quoteTotalAction()
|
14 |
+
{
|
15 |
+
// Grab the quote
|
16 |
+
$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
|
17 |
+
|
18 |
+
// Build up our JSON response
|
19 |
+
$jsonResponse = array(
|
20 |
+
'billingName' => $quote->getBillingAddress()->getName(),
|
21 |
+
'billingPostcode' => $quote->getBillingAddress()->getPostcode(),
|
22 |
+
'grandTotal' => number_format($quote->getGrandTotal(), 2),
|
23 |
+
'currencyCode' => $quote->getQuoteCurrencyCode()
|
24 |
+
);
|
25 |
+
|
26 |
+
// Set the response
|
27 |
+
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($jsonResponse));
|
28 |
+
return false;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Tokenize the card tokens via Ajax
|
33 |
+
*/
|
34 |
+
public function tokenizeCardAction()
|
35 |
+
{
|
36 |
+
// Are tokens set in the request
|
37 |
+
if($tokens = $this->getRequest()->getParam('tokens')) {
|
38 |
+
|
39 |
+
// Build up our response
|
40 |
+
$jsonResponse = array(
|
41 |
+
'success' => true,
|
42 |
+
'tokens' => array()
|
43 |
+
);
|
44 |
+
|
45 |
+
// Json decode the tokens
|
46 |
+
$tokens = Mage::helper('core')->jsonDecode($tokens);
|
47 |
+
if(is_array($tokens)) {
|
48 |
+
|
49 |
+
// Loop through each token and tokenize it again
|
50 |
+
foreach($tokens as $token) {
|
51 |
+
$jsonResponse['tokens'][$token] = Mage::getSingleton('gene_braintree/wrapper_braintree')->getThreeDSecureVaultNonce($token);
|
52 |
+
}
|
53 |
+
|
54 |
+
// Set the response
|
55 |
+
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($jsonResponse));
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
}
|
app/code/community/Gene/Braintree/controllers/SavedController.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Gene_Braintree_SavedController
|
5 |
+
*
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
class Gene_Braintree_SavedController extends Mage_Core_Controller_Front_Action
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Retrieve customer session object
|
13 |
+
*
|
14 |
+
* @return Mage_Customer_Model_Session
|
15 |
+
*/
|
16 |
+
protected function _getSession()
|
17 |
+
{
|
18 |
+
return Mage::getSingleton('customer/session');
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Validate that the user is logged in
|
23 |
+
*/
|
24 |
+
public function preDispatch()
|
25 |
+
{
|
26 |
+
parent::preDispatch();
|
27 |
+
|
28 |
+
if (!Mage::getSingleton('customer/session')->authenticate($this)) {
|
29 |
+
$this->setFlag('', 'no-dispatch', true);
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Show the listing page of saved payment information
|
35 |
+
*/
|
36 |
+
public function indexAction()
|
37 |
+
{
|
38 |
+
$this->loadLayout();
|
39 |
+
|
40 |
+
$this->_initLayoutMessages('customer/session');
|
41 |
+
$this->_initLayoutMessages('catalog/session');
|
42 |
+
|
43 |
+
$this->getLayout()->getBlock('head')->setTitle($this->__('Saved Payment Information'));
|
44 |
+
|
45 |
+
$this->renderLayout();
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Action to allow users to delete payment methods
|
50 |
+
*
|
51 |
+
* @return Mage_Core_Controller_Varien_Action
|
52 |
+
*
|
53 |
+
* @throws Exception
|
54 |
+
*/
|
55 |
+
public function removeAction()
|
56 |
+
{
|
57 |
+
// Check we've recieved a payment ID
|
58 |
+
$token = $this->getRequest()->getParam('id');
|
59 |
+
if(!$token) {
|
60 |
+
$this->_getSession()->addError('Please select a saved payment entry to remove.');
|
61 |
+
return $this->_redirectReferer();
|
62 |
+
}
|
63 |
+
|
64 |
+
// Grab a new instance of the wrapper
|
65 |
+
$wrapper = Mage::getModel('gene_braintree/wrapper_braintree');
|
66 |
+
|
67 |
+
// Init the braintree wrapper
|
68 |
+
$wrapper->init();
|
69 |
+
|
70 |
+
// Load the payment method from Braintree
|
71 |
+
try {
|
72 |
+
$paymentMethod = Braintree_PaymentMethod::find($token);
|
73 |
+
} catch (Exception $e) {
|
74 |
+
$this->_getSession()->addError('The requested payment method cannot be found.');
|
75 |
+
return $this->_redirectReferer();
|
76 |
+
}
|
77 |
+
|
78 |
+
// Check that this is the users payment method, we have to use a custom method as Braintree don't return the PayPal customer ID
|
79 |
+
if(!$wrapper->customerOwnsMethod($paymentMethod)) {
|
80 |
+
$this->_getSession()->addError('You do not have permission to modify this payment method.');
|
81 |
+
return $this->_redirectReferer();
|
82 |
+
}
|
83 |
+
|
84 |
+
// Remove the payment method
|
85 |
+
Braintree_PaymentMethod::delete($token);
|
86 |
+
|
87 |
+
// Inform the user of the great news
|
88 |
+
$this->_getSession()->addSuccess('Saved payment has been successfully deleted.');
|
89 |
+
return $this->_redirectReferer();
|
90 |
+
}
|
91 |
+
|
92 |
+
}
|
app/code/community/Gene/Braintree/etc/adminhtml.xml
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<all>
|
6 |
+
<title>Allow Everything</title>
|
7 |
+
</all>
|
8 |
+
<admin>
|
9 |
+
<children>
|
10 |
+
<report>
|
11 |
+
<children>
|
12 |
+
<salesroot>
|
13 |
+
<children>
|
14 |
+
<braintree_transactions translate="title">
|
15 |
+
<title>Braintree Transactions</title>
|
16 |
+
<sort_order>100</sort_order>
|
17 |
+
</braintree_transactions>
|
18 |
+
</children>
|
19 |
+
</salesroot>
|
20 |
+
</children>
|
21 |
+
</report>
|
22 |
+
</children>
|
23 |
+
</admin>
|
24 |
+
</resources>
|
25 |
+
</acl>
|
26 |
+
<menu>
|
27 |
+
<report>
|
28 |
+
<children>
|
29 |
+
<salesroot>
|
30 |
+
<children>
|
31 |
+
<braintree_transactions translate="title" module="gene_braintree">
|
32 |
+
<sort_order>11</sort_order>
|
33 |
+
<title>Braintree Transactions</title>
|
34 |
+
<action>adminhtml/braintree/transactions</action>
|
35 |
+
</braintree_transactions>
|
36 |
+
</children>
|
37 |
+
</salesroot>
|
38 |
+
</children>
|
39 |
+
</report>
|
40 |
+
</menu>
|
41 |
+
</config>
|
app/code/community/Gene/Braintree/etc/config.xml
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Gene_Braintree>
|
5 |
+
<version>1.0.0</version>
|
6 |
+
</Gene_Braintree>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<models>
|
10 |
+
<gene_braintree>
|
11 |
+
<class>Gene_Braintree_Model</class>
|
12 |
+
<resourceModel>gene_braintree_resource</resourceModel>
|
13 |
+
</gene_braintree>
|
14 |
+
<gene_braintree_resource>
|
15 |
+
<class>Gene_Braintree_Model_Resource</class>
|
16 |
+
</gene_braintree_resource>
|
17 |
+
</models>
|
18 |
+
<blocks>
|
19 |
+
<gene_braintree>
|
20 |
+
<class>Gene_Braintree_Block</class>
|
21 |
+
</gene_braintree>
|
22 |
+
|
23 |
+
<checkout>
|
24 |
+
<rewrite>
|
25 |
+
<cart_totals>Gene_Braintree_Block_Cart_Totals</cart_totals>
|
26 |
+
</rewrite>
|
27 |
+
</checkout>
|
28 |
+
</blocks>
|
29 |
+
<helpers>
|
30 |
+
<gene_braintree>
|
31 |
+
<class>Gene_Braintree_Helper</class>
|
32 |
+
</gene_braintree>
|
33 |
+
</helpers>
|
34 |
+
|
35 |
+
<resources>
|
36 |
+
<gene_braintree_setup>
|
37 |
+
<setup>
|
38 |
+
<module>Gene_Braintree</module>
|
39 |
+
<class>Mage_Eav_Model_Entity_Setup</class>
|
40 |
+
</setup>
|
41 |
+
</gene_braintree_setup>
|
42 |
+
</resources>
|
43 |
+
|
44 |
+
<payment>
|
45 |
+
<cc>
|
46 |
+
<types>
|
47 |
+
<ME>
|
48 |
+
<code>ME</code>
|
49 |
+
<name>Maestro</name>
|
50 |
+
<order>10</order>
|
51 |
+
</ME>
|
52 |
+
</types>
|
53 |
+
</cc>
|
54 |
+
</payment>
|
55 |
+
</global>
|
56 |
+
|
57 |
+
<!-- Default values for the system configuration pages -->
|
58 |
+
<default>
|
59 |
+
<payment>
|
60 |
+
<!-- Core settings within the module -->
|
61 |
+
<gene_braintree>
|
62 |
+
<debug>0</debug>
|
63 |
+
<multi_currency_enable>0</multi_currency_enable>
|
64 |
+
</gene_braintree>
|
65 |
+
|
66 |
+
<!-- PayPal method -->
|
67 |
+
<gene_braintree_paypal>
|
68 |
+
<active>0</active>
|
69 |
+
<model>gene_braintree/paymentmethod_paypal</model>
|
70 |
+
<order_status>processing</order_status>
|
71 |
+
<payment_action>authorize_capture</payment_action>
|
72 |
+
<title>PayPal (Braintree)</title>
|
73 |
+
<environment>sandbox</environment>
|
74 |
+
<allowspecific>0</allowspecific>
|
75 |
+
<payment_type>single</payment_type>
|
76 |
+
<use_vault>0</use_vault>
|
77 |
+
<locale>en_gb</locale>
|
78 |
+
</gene_braintree_paypal>
|
79 |
+
|
80 |
+
<!-- Credit Card method -->
|
81 |
+
<gene_braintree_creditcard>
|
82 |
+
<active>0</active>
|
83 |
+
<model>gene_braintree/paymentmethod_creditcard</model>
|
84 |
+
<order_status>processing</order_status>
|
85 |
+
<payment_action>authorize</payment_action>
|
86 |
+
<title>Credit Card (Braintree)</title>
|
87 |
+
<environment>sandbox</environment>
|
88 |
+
<allowspecific>0</allowspecific>
|
89 |
+
<use_vault>0</use_vault>
|
90 |
+
<useccv>1</useccv>
|
91 |
+
</gene_braintree_creditcard>
|
92 |
+
|
93 |
+
</payment>
|
94 |
+
</default>
|
95 |
+
|
96 |
+
<frontend>
|
97 |
+
<layout>
|
98 |
+
<updates>
|
99 |
+
<gene_braintree module="Gene_Braintree">
|
100 |
+
<file>gene/braintree.xml</file>
|
101 |
+
</gene_braintree>
|
102 |
+
</updates>
|
103 |
+
</layout>
|
104 |
+
|
105 |
+
<routers>
|
106 |
+
<braintree>
|
107 |
+
<use>standard</use>
|
108 |
+
<args>
|
109 |
+
<module>Gene_Braintree</module>
|
110 |
+
<frontName>braintree</frontName>
|
111 |
+
</args>
|
112 |
+
</braintree>
|
113 |
+
</routers>
|
114 |
+
|
115 |
+
<translate>
|
116 |
+
<modules>
|
117 |
+
<Gene_Braintree>
|
118 |
+
<files>
|
119 |
+
<default>Gene_Braintree.csv</default>
|
120 |
+
</files>
|
121 |
+
</Gene_Braintree>
|
122 |
+
</modules>
|
123 |
+
</translate>
|
124 |
+
|
125 |
+
<events>
|
126 |
+
<checkout_submit_all_after>
|
127 |
+
<observers>
|
128 |
+
<gene_braintree_save_customer_id>
|
129 |
+
<type>singleton</type>
|
130 |
+
<class>gene_braintree/observer</class>
|
131 |
+
<method>completeCheckout</method>
|
132 |
+
</gene_braintree_save_customer_id>
|
133 |
+
</observers>
|
134 |
+
</checkout_submit_all_after>
|
135 |
+
|
136 |
+
<controller_action_layout_load_before>
|
137 |
+
<observers>
|
138 |
+
<gene_braintree_detect_checkout>
|
139 |
+
<type>singleton</type>
|
140 |
+
<class>gene_braintree/observer</class>
|
141 |
+
<method>addLayoutHandle</method>
|
142 |
+
</gene_braintree_detect_checkout>
|
143 |
+
</observers>
|
144 |
+
</controller_action_layout_load_before>
|
145 |
+
</events>
|
146 |
+
</frontend>
|
147 |
+
|
148 |
+
<adminhtml>
|
149 |
+
<layout>
|
150 |
+
<updates>
|
151 |
+
<gene_braintree>
|
152 |
+
<file>gene/braintree.xml</file>
|
153 |
+
</gene_braintree>
|
154 |
+
</updates>
|
155 |
+
</layout>
|
156 |
+
|
157 |
+
<translate>
|
158 |
+
<modules>
|
159 |
+
<Gene_Braintree>
|
160 |
+
<files>
|
161 |
+
<default>Gene_Braintree.csv</default>
|
162 |
+
</files>
|
163 |
+
</Gene_Braintree>
|
164 |
+
</modules>
|
165 |
+
</translate>
|
166 |
+
|
167 |
+
<events>
|
168 |
+
<sales_order_shipment_save_after>
|
169 |
+
<observers>
|
170 |
+
<capture_braintree_payment>
|
171 |
+
<class>gene_braintree/observer</class>
|
172 |
+
<method>captureBraintreePayment</method>
|
173 |
+
</capture_braintree_payment>
|
174 |
+
</observers>
|
175 |
+
</sales_order_shipment_save_after>
|
176 |
+
</events>
|
177 |
+
</adminhtml>
|
178 |
+
|
179 |
+
<admin>
|
180 |
+
<routers>
|
181 |
+
<adminhtml>
|
182 |
+
<args>
|
183 |
+
<modules>
|
184 |
+
<Gene_Braintree before="Mage_Adminhtml">Gene_Braintree_Adminhtml</Gene_Braintree>
|
185 |
+
</modules>
|
186 |
+
</args>
|
187 |
+
</adminhtml>
|
188 |
+
</routers>
|
189 |
+
</admin>
|
190 |
+
|
191 |
+
</config>
|
app/code/community/Gene/Braintree/etc/system.xml
ADDED
@@ -0,0 +1,500 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<payment>
|
5 |
+
<groups>
|
6 |
+
<gene_braintree translate="label comment" module="gene_braintree">
|
7 |
+
<label>Braintree v.zero - Configuration</label>
|
8 |
+
<sort_order>1498</sort_order>
|
9 |
+
<show_in_default>1</show_in_default>
|
10 |
+
<show_in_website>1</show_in_website>
|
11 |
+
<show_in_store>1</show_in_store>
|
12 |
+
<comment><![CDATA[<img src="https://i.imgur.com/JR1BJTr.png" style="margin: 4px 0 8px 0;" border="0"/><br />To use this module you will need an existing production or sandbox Braintree account. You can apply at <a href="https://www.braintreepayments.com">braintreepayments.com</a>.<br />Braintree v.zero integration provided by <a href="http://gene.co.uk/" target="_blank">Gene Commerce</a>.]]></comment>
|
13 |
+
<fields>
|
14 |
+
|
15 |
+
<module_version translate="label">
|
16 |
+
<label>Magento Braintree v.zero Version</label>
|
17 |
+
<frontend_model>gene_braintree/adminhtml_system_config_braintree_moduleversion</frontend_model>
|
18 |
+
<sort_order>20</sort_order>
|
19 |
+
<show_in_default>1</show_in_default>
|
20 |
+
<show_in_website>1</show_in_website>
|
21 |
+
<show_in_store>1</show_in_store>
|
22 |
+
</module_version>
|
23 |
+
|
24 |
+
<lib_version translate="label">
|
25 |
+
<label>Braintree PHP SDK Version</label>
|
26 |
+
<frontend_model>gene_braintree/adminhtml_system_config_braintree_version</frontend_model>
|
27 |
+
<sort_order>20</sort_order>
|
28 |
+
<show_in_default>1</show_in_default>
|
29 |
+
<show_in_website>1</show_in_website>
|
30 |
+
<show_in_store>1</show_in_store>
|
31 |
+
</lib_version>
|
32 |
+
|
33 |
+
<braintree_details translate="label">
|
34 |
+
<label>Braintree Account Details</label>
|
35 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
36 |
+
<sort_order>30</sort_order>
|
37 |
+
<show_in_default>1</show_in_default>
|
38 |
+
<show_in_website>1</show_in_website>
|
39 |
+
<show_in_store>1</show_in_store>
|
40 |
+
</braintree_details>
|
41 |
+
|
42 |
+
<environment translate="label comment">
|
43 |
+
<label>Environment</label>
|
44 |
+
<frontend_type>select</frontend_type>
|
45 |
+
<source_model>gene_braintree/source_environment</source_model>
|
46 |
+
<sort_order>31</sort_order>
|
47 |
+
<show_in_default>1</show_in_default>
|
48 |
+
<show_in_website>1</show_in_website>
|
49 |
+
<show_in_store>0</show_in_store>
|
50 |
+
<comment><![CDATA[
|
51 |
+
<strong>Warning:</strong> Do not use 'Sandbox' on a production environment.<br />
|
52 |
+
Your API details above will need to reflect your Sandbox or your Production account.
|
53 |
+
]]></comment>
|
54 |
+
<frontend_class>validate-config</frontend_class>
|
55 |
+
</environment>
|
56 |
+
|
57 |
+
<merchant_id translate="label">
|
58 |
+
<label>Merchant ID</label>
|
59 |
+
<frontend_type>text</frontend_type>
|
60 |
+
<sort_order>35</sort_order>
|
61 |
+
<show_in_default>1</show_in_default>
|
62 |
+
<show_in_website>1</show_in_website>
|
63 |
+
<show_in_store>0</show_in_store>
|
64 |
+
<frontend_class>validate-config</frontend_class>
|
65 |
+
</merchant_id>
|
66 |
+
|
67 |
+
<merchant_account_id translate="label">
|
68 |
+
<label>Merchant Account ID</label>
|
69 |
+
<frontend_type>text</frontend_type>
|
70 |
+
<sort_order>40</sort_order>
|
71 |
+
<show_in_default>1</show_in_default>
|
72 |
+
<show_in_website>1</show_in_website>
|
73 |
+
<show_in_store>1</show_in_store>
|
74 |
+
<frontend_class>validate-config</frontend_class>
|
75 |
+
<comment><![CDATA[
|
76 |
+
If you're accepting different currencies across multiple store views/websites you'll need to adjust your merchant account ID in the correct scope, if you're using the Magento currency switcher you'll need to enable the section below.
|
77 |
+
]]></comment>
|
78 |
+
</merchant_account_id>
|
79 |
+
|
80 |
+
<public_key translate="label">
|
81 |
+
<label>Public Key</label>
|
82 |
+
<frontend_type>text</frontend_type>
|
83 |
+
<sort_order>45</sort_order>
|
84 |
+
<show_in_default>1</show_in_default>
|
85 |
+
<show_in_website>1</show_in_website>
|
86 |
+
<show_in_store>0</show_in_store>
|
87 |
+
<frontend_class>validate-config</frontend_class>
|
88 |
+
</public_key>
|
89 |
+
|
90 |
+
<private_key translate="label">
|
91 |
+
<label>Private Key</label>
|
92 |
+
<frontend_type>text</frontend_type>
|
93 |
+
<sort_order>50</sort_order>
|
94 |
+
<show_in_default>1</show_in_default>
|
95 |
+
<show_in_website>1</show_in_website>
|
96 |
+
<show_in_store>0</show_in_store>
|
97 |
+
<frontend_class>validate-config</frontend_class>
|
98 |
+
</private_key>
|
99 |
+
|
100 |
+
<valid_config translate="label">
|
101 |
+
<label />
|
102 |
+
<frontend_model>gene_braintree/adminhtml_system_config_braintree_config</frontend_model>
|
103 |
+
<sort_order>55</sort_order>
|
104 |
+
<show_in_default>1</show_in_default>
|
105 |
+
<show_in_website>1</show_in_website>
|
106 |
+
<show_in_store>0</show_in_store>
|
107 |
+
</valid_config>
|
108 |
+
|
109 |
+
<multi_currency_heading translate="label">
|
110 |
+
<label>Currency Switcher</label>
|
111 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
112 |
+
<sort_order>60</sort_order>
|
113 |
+
<show_in_default>1</show_in_default>
|
114 |
+
<show_in_website>1</show_in_website>
|
115 |
+
<show_in_store>0</show_in_store>
|
116 |
+
</multi_currency_heading>
|
117 |
+
|
118 |
+
<multi_currency_enable>
|
119 |
+
<label>Enabled?</label>
|
120 |
+
<frontend_type>select</frontend_type>
|
121 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
122 |
+
<sort_order>65</sort_order>
|
123 |
+
<show_in_default>1</show_in_default>
|
124 |
+
<show_in_website>1</show_in_website>
|
125 |
+
<show_in_store>0</show_in_store>
|
126 |
+
<comment><![CDATA[
|
127 |
+
If you're using the Magento built in currency switcher you'll need to activate this section to ensure the customers payment goes into your correct merchant account. If you use store views for separate countries you do not need this feature enabled. <br /><strong>Note:</strong> The invoices will still show up as your base currency, but the customer will be charged in their selected currency for the correct amount.
|
128 |
+
]]></comment>
|
129 |
+
</multi_currency_enable>
|
130 |
+
|
131 |
+
<multi_currency_mapping translate="label">
|
132 |
+
<label>Mapping</label>
|
133 |
+
<backend_model>gene_braintree/system_config_backend_currency</backend_model>
|
134 |
+
<frontend_model>gene_braintree/adminhtml_system_config_braintree_currency</frontend_model>
|
135 |
+
<sort_order>70</sort_order>
|
136 |
+
<show_in_default>1</show_in_default>
|
137 |
+
<show_in_website>1</show_in_website>
|
138 |
+
<show_in_store>0</show_in_store>
|
139 |
+
<depends>
|
140 |
+
<multi_currency_enable>1</multi_currency_enable>
|
141 |
+
</depends>
|
142 |
+
<comment><![CDATA[
|
143 |
+
You need to supply each merchant account ID for each enabled currency.
|
144 |
+
]]></comment>
|
145 |
+
</multi_currency_mapping>
|
146 |
+
|
147 |
+
<settings translate="label">
|
148 |
+
<label>Testing Settings</label>
|
149 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
150 |
+
<sort_order>80</sort_order>
|
151 |
+
<show_in_default>1</show_in_default>
|
152 |
+
<show_in_website>1</show_in_website>
|
153 |
+
<show_in_store>1</show_in_store>
|
154 |
+
</settings>
|
155 |
+
|
156 |
+
<debug translate="label comment">
|
157 |
+
<label>Debug</label>
|
158 |
+
<frontend_type>select</frontend_type>
|
159 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
160 |
+
<sort_order>85</sort_order>
|
161 |
+
<show_in_default>1</show_in_default>
|
162 |
+
<show_in_website>1</show_in_website>
|
163 |
+
<show_in_store>1</show_in_store>
|
164 |
+
<comment><![CDATA[
|
165 |
+
Debugging will cause a log to be written to the <strong>var/log/gene_braintree.log</strong> file. As no credit card data ever hits the server this file will never contain any crucial customer information.
|
166 |
+
]]></comment>
|
167 |
+
</debug>
|
168 |
+
|
169 |
+
</fields>
|
170 |
+
</gene_braintree>
|
171 |
+
|
172 |
+
<gene_braintree_paypal translate="label comment" module="gene_braintree">
|
173 |
+
<label>Braintree v.zero - PayPal</label>
|
174 |
+
<sort_order>1499</sort_order>
|
175 |
+
<show_in_default>1</show_in_default>
|
176 |
+
<show_in_website>1</show_in_website>
|
177 |
+
<show_in_store>1</show_in_store>
|
178 |
+
<comment><![CDATA[<img src="https://i.imgur.com/sitDbHA.png" style="margin: 6px 0;" /><br />You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details.]]></comment>
|
179 |
+
<fields>
|
180 |
+
|
181 |
+
<active translate="label">
|
182 |
+
<label>Enabled</label>
|
183 |
+
<frontend_type>select</frontend_type>
|
184 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
185 |
+
<sort_order>1</sort_order>
|
186 |
+
<show_in_default>1</show_in_default>
|
187 |
+
<show_in_website>1</show_in_website>
|
188 |
+
<show_in_store>0</show_in_store>
|
189 |
+
</active>
|
190 |
+
|
191 |
+
<title translate="label">
|
192 |
+
<label>Title</label>
|
193 |
+
<frontend_type>text</frontend_type>
|
194 |
+
<sort_order>2</sort_order>
|
195 |
+
<show_in_default>1</show_in_default>
|
196 |
+
<show_in_website>1</show_in_website>
|
197 |
+
<show_in_store>1</show_in_store>
|
198 |
+
</title>
|
199 |
+
|
200 |
+
<capture_heading translate="label">
|
201 |
+
<label>Capture</label>
|
202 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
203 |
+
<sort_order>5</sort_order>
|
204 |
+
<show_in_default>1</show_in_default>
|
205 |
+
<show_in_website>1</show_in_website>
|
206 |
+
<show_in_store>1</show_in_store>
|
207 |
+
</capture_heading>
|
208 |
+
|
209 |
+
<order_status translate="label">
|
210 |
+
<label>Complete Order Status</label>
|
211 |
+
<frontend_type>select</frontend_type>
|
212 |
+
<source_model>adminhtml/system_config_source_order_status_processing</source_model>
|
213 |
+
<sort_order>10</sort_order>
|
214 |
+
<show_in_default>1</show_in_default>
|
215 |
+
<show_in_website>1</show_in_website>
|
216 |
+
<show_in_store>1</show_in_store>
|
217 |
+
</order_status>
|
218 |
+
|
219 |
+
<features_heading translate="label">
|
220 |
+
<label>Features</label>
|
221 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
222 |
+
<sort_order>70</sort_order>
|
223 |
+
<show_in_default>1</show_in_default>
|
224 |
+
<show_in_website>1</show_in_website>
|
225 |
+
<show_in_store>1</show_in_store>
|
226 |
+
</features_heading>
|
227 |
+
|
228 |
+
<payment_type translate="label comment">
|
229 |
+
<label>Payment Type</label>
|
230 |
+
<frontend_type>select</frontend_type>
|
231 |
+
<source_model>gene_braintree/source_paypal_paymenttype</source_model>
|
232 |
+
<sort_order>75</sort_order>
|
233 |
+
<show_in_default>1</show_in_default>
|
234 |
+
<show_in_website>1</show_in_website>
|
235 |
+
<show_in_store>1</show_in_store>
|
236 |
+
<comment><![CDATA[
|
237 |
+
<strong>Single Payment</strong> - Will only require the customer to sign in, we will only be able to take a single payment<br />
|
238 |
+
<strong>Future Payments</strong> - Allows us to save the customers PayPal account for later purchases and use with the Vault
|
239 |
+
]]></comment>
|
240 |
+
</payment_type>
|
241 |
+
|
242 |
+
<locale translate="label comment">
|
243 |
+
<label>Locale</label>
|
244 |
+
<frontend_type>select</frontend_type>
|
245 |
+
<source_model>gene_braintree/source_paypal_locale</source_model>
|
246 |
+
<sort_order>80</sort_order>
|
247 |
+
<show_in_default>1</show_in_default>
|
248 |
+
<show_in_website>1</show_in_website>
|
249 |
+
<show_in_store>1</show_in_store>
|
250 |
+
<depends>
|
251 |
+
<payment_type>single</payment_type>
|
252 |
+
</depends>
|
253 |
+
<comment><![CDATA[
|
254 |
+
The locale for the PayPal popup window
|
255 |
+
]]></comment>
|
256 |
+
</locale>
|
257 |
+
|
258 |
+
<use_vault translate="label comment">
|
259 |
+
<label>Enable Vault</label>
|
260 |
+
<frontend_type>select</frontend_type>
|
261 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
262 |
+
<sort_order>80</sort_order>
|
263 |
+
<show_in_default>1</show_in_default>
|
264 |
+
<show_in_website>1</show_in_website>
|
265 |
+
<show_in_store>1</show_in_store>
|
266 |
+
<depends>
|
267 |
+
<payment_type>future</payment_type>
|
268 |
+
</depends>
|
269 |
+
<comment><![CDATA[
|
270 |
+
Storing the customers PayPal in the vault will allow them to instantly purchase any product without having to login to PayPal again.
|
271 |
+
]]></comment>
|
272 |
+
</use_vault>
|
273 |
+
|
274 |
+
<display_heading translate="label">
|
275 |
+
<label>Display</label>
|
276 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
277 |
+
<sort_order>100</sort_order>
|
278 |
+
<show_in_default>1</show_in_default>
|
279 |
+
<show_in_website>1</show_in_website>
|
280 |
+
<show_in_store>1</show_in_store>
|
281 |
+
</display_heading>
|
282 |
+
|
283 |
+
<sort_order translate="label">
|
284 |
+
<label>Sort Order</label>
|
285 |
+
<frontend_type>text</frontend_type>
|
286 |
+
<sort_order>150</sort_order>
|
287 |
+
<show_in_default>1</show_in_default>
|
288 |
+
<show_in_website>1</show_in_website>
|
289 |
+
<show_in_store>1</show_in_store>
|
290 |
+
</sort_order>
|
291 |
+
|
292 |
+
</fields>
|
293 |
+
</gene_braintree_paypal>
|
294 |
+
|
295 |
+
<gene_braintree_creditcard translate="label comment" module="gene_braintree">
|
296 |
+
<label>Braintree v.zero - Credit Card</label>
|
297 |
+
<sort_order>1500</sort_order>
|
298 |
+
<show_in_default>1</show_in_default>
|
299 |
+
<show_in_website>1</show_in_website>
|
300 |
+
<show_in_store>1</show_in_store>
|
301 |
+
<comment><![CDATA[You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details.]]></comment>
|
302 |
+
<fields>
|
303 |
+
|
304 |
+
<active translate="label">
|
305 |
+
<label>Enabled</label>
|
306 |
+
<frontend_type>select</frontend_type>
|
307 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
308 |
+
<sort_order>1</sort_order>
|
309 |
+
<show_in_default>1</show_in_default>
|
310 |
+
<show_in_website>1</show_in_website>
|
311 |
+
<show_in_store>0</show_in_store>
|
312 |
+
</active>
|
313 |
+
|
314 |
+
<title translate="label">
|
315 |
+
<label>Title</label>
|
316 |
+
<frontend_type>text</frontend_type>
|
317 |
+
<sort_order>2</sort_order>
|
318 |
+
<show_in_default>1</show_in_default>
|
319 |
+
<show_in_website>1</show_in_website>
|
320 |
+
<show_in_store>1</show_in_store>
|
321 |
+
</title>
|
322 |
+
|
323 |
+
<capture_heading translate="label">
|
324 |
+
<label>Capture</label>
|
325 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
326 |
+
<sort_order>5</sort_order>
|
327 |
+
<show_in_default>1</show_in_default>
|
328 |
+
<show_in_website>1</show_in_website>
|
329 |
+
<show_in_store>1</show_in_store>
|
330 |
+
</capture_heading>
|
331 |
+
|
332 |
+
<payment_action translate="label comment">
|
333 |
+
<label>Payment Action</label>
|
334 |
+
<frontend_type>select</frontend_type>
|
335 |
+
<source_model>gene_braintree/source_creditcard_paymentAction</source_model>
|
336 |
+
<sort_order>9</sort_order>
|
337 |
+
<show_in_default>1</show_in_default>
|
338 |
+
<show_in_website>1</show_in_website>
|
339 |
+
<show_in_store>0</show_in_store>
|
340 |
+
<comment><![CDATA[
|
341 |
+
<strong>Authorize</strong> - Will only auth the payment and store a token, the transaction will not be settled.<br />
|
342 |
+
<strong>Authorize & Capture</strong> - We will instantly settle the transaction within the checkout.
|
343 |
+
]]></comment>
|
344 |
+
</payment_action>
|
345 |
+
|
346 |
+
<capture_action translate="label comment">
|
347 |
+
<label>Capture Action</label>
|
348 |
+
<frontend_type>select</frontend_type>
|
349 |
+
<source_model>gene_braintree/source_creditcard_captureAction</source_model>
|
350 |
+
<sort_order>10</sort_order>
|
351 |
+
<show_in_default>1</show_in_default>
|
352 |
+
<show_in_website>1</show_in_website>
|
353 |
+
<show_in_store>0</show_in_store>
|
354 |
+
<comment><![CDATA[
|
355 |
+
If you're just authorizing transactions you can define at what point they should be submitted for settlement.
|
356 |
+
]]></comment>
|
357 |
+
<depends>
|
358 |
+
<payment_action>authorize</payment_action>
|
359 |
+
</depends>
|
360 |
+
</capture_action>
|
361 |
+
|
362 |
+
<order_status translate="label">
|
363 |
+
<label>New Order Status</label>
|
364 |
+
<frontend_type>select</frontend_type>
|
365 |
+
<source_model>adminhtml/system_config_source_order_status_processing</source_model>
|
366 |
+
<sort_order>20</sort_order>
|
367 |
+
<show_in_default>1</show_in_default>
|
368 |
+
<show_in_website>1</show_in_website>
|
369 |
+
<show_in_store>1</show_in_store>
|
370 |
+
</order_status>
|
371 |
+
|
372 |
+
<features_heading translate="label">
|
373 |
+
<label>Features</label>
|
374 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
375 |
+
<sort_order>70</sort_order>
|
376 |
+
<show_in_default>1</show_in_default>
|
377 |
+
<show_in_website>1</show_in_website>
|
378 |
+
<show_in_store>1</show_in_store>
|
379 |
+
</features_heading>
|
380 |
+
|
381 |
+
<use_vault translate="label comment">
|
382 |
+
<label>Enable Vault/Saved Cards</label>
|
383 |
+
<frontend_type>select</frontend_type>
|
384 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
385 |
+
<sort_order>75</sort_order>
|
386 |
+
<show_in_default>1</show_in_default>
|
387 |
+
<show_in_website>1</show_in_website>
|
388 |
+
<show_in_store>1</show_in_store>
|
389 |
+
<comment><![CDATA[
|
390 |
+
The vault allows you to securely store the customers credit card on Braintree's servers. We're provided with a token which allows the customer to make future payments without having to enter any details again.
|
391 |
+
]]></comment>
|
392 |
+
</use_vault>
|
393 |
+
|
394 |
+
<threedsecure translate="label comment">
|
395 |
+
<label>Enable 3D Secure</label>
|
396 |
+
<frontend_type>select</frontend_type>
|
397 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
398 |
+
<sort_order>76</sort_order>
|
399 |
+
<show_in_default>1</show_in_default>
|
400 |
+
<show_in_website>1</show_in_website>
|
401 |
+
<show_in_store>1</show_in_store>
|
402 |
+
<comment><![CDATA[
|
403 |
+
The 3D Secure feature enables the shopper to enter a password to confirm their identity with the card issuer. If accepted they then complete their order, and when received by you, you have much more confidence that is genuine and real.
|
404 |
+
]]></comment>
|
405 |
+
</threedsecure>
|
406 |
+
|
407 |
+
<useccv translate="label comment">
|
408 |
+
<label>CVV Verification</label>
|
409 |
+
<frontend_type>select</frontend_type>
|
410 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
411 |
+
<sort_order>76</sort_order>
|
412 |
+
<show_in_default>1</show_in_default>
|
413 |
+
<show_in_website>1</show_in_website>
|
414 |
+
<show_in_store>1</show_in_store>
|
415 |
+
<comment><![CDATA[
|
416 |
+
Should we verify the CVV against the card?
|
417 |
+
]]></comment>
|
418 |
+
</useccv>
|
419 |
+
|
420 |
+
<kount_merchant_id translate="label comment">
|
421 |
+
<label>Kount Merchant ID</label>
|
422 |
+
<frontend_type>text</frontend_type>
|
423 |
+
<sort_order>78</sort_order>
|
424 |
+
<show_in_default>1</show_in_default>
|
425 |
+
<show_in_website>1</show_in_website>
|
426 |
+
<show_in_store>1</show_in_store>
|
427 |
+
<comment><![CDATA[
|
428 |
+
Braintree offers a direct integration with Kount, our partner for providing advanced fraud detection technology. To use this feature, you must be processing at least 2500 transactions per month, and you’ll be subject to additional fees from Kount for their services. To get started, contact accounts@braintreepayments.com. You can view more information <a href="https://developers.braintreepayments.com/javascript+php/guides/fraud-tools">here</a>.
|
429 |
+
]]></comment>
|
430 |
+
</kount_merchant_id>
|
431 |
+
|
432 |
+
<cctypes translate="label">
|
433 |
+
<label>Credit Card Types</label>
|
434 |
+
<frontend_type>multiselect</frontend_type>
|
435 |
+
<source_model>gene_braintree/source_cctype</source_model>
|
436 |
+
<sort_order>85</sort_order>
|
437 |
+
<show_in_default>1</show_in_default>
|
438 |
+
<show_in_website>1</show_in_website>
|
439 |
+
<show_in_store>0</show_in_store>
|
440 |
+
</cctypes>
|
441 |
+
|
442 |
+
<allowspecific translate="label">
|
443 |
+
<label>Payment from Applicable Countries</label>
|
444 |
+
<frontend_type>allowspecific</frontend_type>
|
445 |
+
<sort_order>90</sort_order>
|
446 |
+
<source_model>adminhtml/system_config_source_payment_allspecificcountries</source_model>
|
447 |
+
<show_in_default>1</show_in_default>
|
448 |
+
<show_in_website>1</show_in_website>
|
449 |
+
<show_in_store>0</show_in_store>
|
450 |
+
</allowspecific>
|
451 |
+
|
452 |
+
<specificcountry translate="label">
|
453 |
+
<label>Payment from Specific Countries</label>
|
454 |
+
<frontend_type>multiselect</frontend_type>
|
455 |
+
<sort_order>95</sort_order>
|
456 |
+
<source_model>adminhtml/system_config_source_country</source_model>
|
457 |
+
<show_in_default>1</show_in_default>
|
458 |
+
<show_in_website>1</show_in_website>
|
459 |
+
<show_in_store>0</show_in_store>
|
460 |
+
</specificcountry>
|
461 |
+
|
462 |
+
<!-- @todo to be included in a future release -->
|
463 |
+
<!--<dynamic_descriptors translate="label comment">-->
|
464 |
+
<!--<label>Dynamic Descriptors</label>-->
|
465 |
+
<!--<frontend_type>select</frontend_type>-->
|
466 |
+
<!--<source_model>adminhtml/system_config_source_yesno</source_model>-->
|
467 |
+
<!--<sort_order>100</sort_order>-->
|
468 |
+
<!--<show_in_default>1</show_in_default>-->
|
469 |
+
<!--<show_in_website>1</show_in_website>-->
|
470 |
+
<!--<show_in_store>0</show_in_store>-->
|
471 |
+
<!--<comment><![CDATA[-->
|
472 |
+
<!--Dyanmic descriptors allow you to modify the entry shown on the customers statement. This will include the company name, company phone number and the company URL.<br />-->
|
473 |
+
<!--<strong>Note:</strong> You must have this enabled on your account, you can find out more information <a href="https://developers.braintreepayments.com/javascript+php/sdk/server/transaction-processing/dynamic-descriptors">here</a>.-->
|
474 |
+
<!--]]></comment>-->
|
475 |
+
<!--</dynamic_descriptors>-->
|
476 |
+
|
477 |
+
<display_heading translate="label">
|
478 |
+
<label>Display</label>
|
479 |
+
<frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
|
480 |
+
<sort_order>145</sort_order>
|
481 |
+
<show_in_default>1</show_in_default>
|
482 |
+
<show_in_website>1</show_in_website>
|
483 |
+
<show_in_store>1</show_in_store>
|
484 |
+
</display_heading>
|
485 |
+
|
486 |
+
<sort_order translate="label">
|
487 |
+
<label>Sort Order</label>
|
488 |
+
<frontend_type>text</frontend_type>
|
489 |
+
<sort_order>150</sort_order>
|
490 |
+
<show_in_default>1</show_in_default>
|
491 |
+
<show_in_website>1</show_in_website>
|
492 |
+
<show_in_store>1</show_in_store>
|
493 |
+
</sort_order>
|
494 |
+
|
495 |
+
</fields>
|
496 |
+
</gene_braintree_creditcard>
|
497 |
+
</groups>
|
498 |
+
</payment>
|
499 |
+
</sections>
|
500 |
+
</config>
|
app/code/community/Gene/Braintree/sql/gene_braintree_setup/install-0.1.0.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$installer = $this;
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
$entityTypeId = $installer->getEntityTypeId('customer');
|
7 |
+
$attributeSetId = $installer->getDefaultAttributeSetId($entityTypeId);
|
8 |
+
$attributeGroupId = $installer->getDefaultAttributeGroupId($entityTypeId, $attributeSetId);
|
9 |
+
|
10 |
+
// Add in a new attribute for the braintree's customer ID
|
11 |
+
// This is generated and stored Magento side and is used for stored details
|
12 |
+
$installer->addAttribute('customer', 'braintree_customer_id', array(
|
13 |
+
'input' => 'text',
|
14 |
+
'type' => 'varchar',
|
15 |
+
'label' => 'Generated Braintree Customer Account ID',
|
16 |
+
'visible' => 0,
|
17 |
+
'required' => 0,
|
18 |
+
'user_defined' => 1,
|
19 |
+
));
|
20 |
+
|
21 |
+
// Add the attribute into the group
|
22 |
+
$installer->addAttributeToGroup(
|
23 |
+
$entityTypeId,
|
24 |
+
$attributeSetId,
|
25 |
+
$attributeGroupId,
|
26 |
+
'braintree_customer_id',
|
27 |
+
'999'
|
28 |
+
);
|
29 |
+
|
30 |
+
$installer->endSetup();
|
app/design/adminhtml/default/default/layout/gene/braintree.xml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
|
4 |
+
<adminhtml_braintree_transactions>
|
5 |
+
<reference name="content">
|
6 |
+
<block type="gene_braintree/adminhtml_report_transactions" name="gene.braintree.report.transactions"
|
7 |
+
template="gene/braintree/transactions/index.phtml">
|
8 |
+
<block type="gene_braintree/adminhtml_report_transactions_search"
|
9 |
+
name="gene.braintree.report.transactions.search" as="search"
|
10 |
+
template="gene/braintree/transactions/search.phtml"/>
|
11 |
+
</block>
|
12 |
+
</reference>
|
13 |
+
</adminhtml_braintree_transactions>
|
14 |
+
|
15 |
+
<adminhtml_sales_order_create_index>
|
16 |
+
<reference name="head">
|
17 |
+
<action method="addJs"><file>gene/braintree/braintree.js</file></action>
|
18 |
+
<action method="addJs"><file>gene/braintree/vzero.js</file></action>
|
19 |
+
</reference>
|
20 |
+
<reference name="before_body_end">
|
21 |
+
<block type="gene_braintree/js" name="gene_braintree_js" template="gene/braintree/js.phtml" />
|
22 |
+
</reference>
|
23 |
+
</adminhtml_sales_order_create_index>
|
24 |
+
|
25 |
+
</layout>
|
app/design/adminhtml/default/default/template/gene/braintree/creditcard.phtml
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/* @var $this Gene_Braintree_Block_Creditcard */
|
3 |
+
$_code = $this->getMethodCode()
|
4 |
+
?>
|
5 |
+
<div id="payment_form_<?php echo $_code ?>" style="display:none;" class="form-list">
|
6 |
+
|
7 |
+
<div id="credit-card-form">
|
8 |
+
<ul class="form-list">
|
9 |
+
<li>
|
10 |
+
<div class="input-box">
|
11 |
+
<label for="<?php echo $_code ?>_cc_type"><?php echo Mage::helper('payment')->__('Credit Card Type') ?> <span class="required">*</span></label><br/>
|
12 |
+
<select id="<?php echo $_code ?>_cc_type" name="payment[cc_type]" class="required-entry validate-cc-type-select">
|
13 |
+
<?php $_ccType = $this->getInfoData('cc_type') ?>
|
14 |
+
<option value=""></option>
|
15 |
+
<?php foreach ($this->getOriginalCcAvailableTypes() as $_typeCode => $_typeName): ?>
|
16 |
+
<option value="<?php echo $_typeCode ?>" <?php if($_typeCode==$_ccType): ?>selected="selected"<?php endif ?>><?php echo $_typeName ?></option>
|
17 |
+
<?php endforeach ?>
|
18 |
+
</select>
|
19 |
+
</div>
|
20 |
+
</li>
|
21 |
+
<li>
|
22 |
+
<div class="input-box">
|
23 |
+
<label for="<?php echo $_code ?>_cc_number"><?php echo Mage::helper('payment')->__('Credit Card Number') ?> <span class="required">*</span></label><br/>
|
24 |
+
<input type="text" data-genebraintree-name="number" name="payment[cc_number]" id="<?php echo $_code ?>_cc_number" title="<?php echo $this->__('Credit Card Number') ?>" class="input-text validate-cc-number validate-cc-type" value=""/>
|
25 |
+
</div>
|
26 |
+
</li>
|
27 |
+
<li>
|
28 |
+
<div class="input-box">
|
29 |
+
<label for="<?php echo $_code ?>_expiration"><?php echo Mage::helper('payment')->__('Expiration Date') ?> <span class="required">*</span></label><br/>
|
30 |
+
<select id="<?php echo $_code ?>_expiration" name="payment[cc_exp_month]" data-genebraintree-name="expiration_month" class="validate-cc-exp required-entry">
|
31 |
+
<?php $_ccExpMonth = $this->getInfoData('cc_exp_month') ?>
|
32 |
+
<?php foreach ($this->getCcMonths() as $k=>$v): ?>
|
33 |
+
<option value="<?php echo $k ?>" <?php if($k==$_ccExpMonth): ?>selected="selected"<?php endif ?>><?php echo $v ?></option>
|
34 |
+
<?php endforeach ?>
|
35 |
+
</select>
|
36 |
+
<?php $_ccExpYear = $this->getInfoData('cc_exp_year') ?>
|
37 |
+
<select id="<?php echo $_code ?>_expiration_yr" name="payment[cc_exp_year]" data-genebraintree-name="expiration_year" class="required-entry">
|
38 |
+
<?php foreach ($this->getCcYears() as $k=>$v): ?>
|
39 |
+
<option value="<?php echo $k ? $k : '' ?>" <?php if($k==$_ccExpYear): ?>selected="selected"<?php endif ?>><?php echo $v ?></option>
|
40 |
+
<?php endforeach ?>
|
41 |
+
</select>
|
42 |
+
</div>
|
43 |
+
</li>
|
44 |
+
<?php echo $this->getChildHtml() ?>
|
45 |
+
<?php if($this->hasVerification()): ?>
|
46 |
+
<li>
|
47 |
+
<div class="input-box">
|
48 |
+
<label for="<?php echo $_code ?>_cc_cid"><?php echo Mage::helper('payment')->__('Card Verification Number') ?> <span class="required">*</span></label><br/>
|
49 |
+
<input type="text" title="<?php echo $this->__('Card Verification Number') ?>" class="input-text cvv required-entry validate-cc-cvn" id="<?php echo $_code ?>_cc_cid" name="payment[cc_cid]" data-genebraintree-name="cvv" value="" />
|
50 |
+
</div>
|
51 |
+
</li>
|
52 |
+
<?php endif; ?>
|
53 |
+
|
54 |
+
</ul>
|
55 |
+
|
56 |
+
<!-- Fields for the payment method -->
|
57 |
+
<input type="hidden" name="payment[payment_method_nonce]" id="creditcard-payment-nonce" />
|
58 |
+
|
59 |
+
<input type="hidden" id="<?php echo $_code ?>_cc_type" value="" />
|
60 |
+
</div>
|
61 |
+
|
62 |
+
</div>
|
63 |
+
|
64 |
+
<style type="text/css">
|
65 |
+
.card-number {
|
66 |
+
position: relative;
|
67 |
+
}
|
68 |
+
|
69 |
+
.card-type {
|
70 |
+
position: absolute;
|
71 |
+
top: 0;
|
72 |
+
left: 6px;
|
73 |
+
}
|
74 |
+
|
75 |
+
.card-number input {
|
76 |
+
height: 46px;
|
77 |
+
text-indent: 54px;
|
78 |
+
}
|
79 |
+
</style>
|
80 |
+
|
81 |
+
<script type="text/javascript">
|
82 |
+
//<![CDATA[
|
83 |
+
Validation.creditCartTypes = $H({
|
84 |
+
'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true],
|
85 |
+
'MC': [new RegExp('^5[1-5][0-9]{14}$'), new RegExp('^[0-9]{3}$'), true],
|
86 |
+
'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true],
|
87 |
+
'DI': [new RegExp('^6011[0-9]{12}$'), new RegExp('^[0-9]{3}$'), true],
|
88 |
+
'JCB': [new RegExp('^(3[0-9]{15}|(2131|1800)[0-9]{11})$'), new RegExp('^[0-9]{4}$'), true],
|
89 |
+
'OT': [false, new RegExp('^([0-9]{3}|[0-9]{4})?$'), false]
|
90 |
+
});
|
91 |
+
//]]>
|
92 |
+
</script>
|
93 |
+
|
94 |
+
<!-- Attach an event onto all radio buttons -->
|
95 |
+
<script type="text/javascript">
|
96 |
+
|
97 |
+
// Verify that vzero is defined before attempting to use it
|
98 |
+
if(typeof vzero !== 'undefined') {
|
99 |
+
|
100 |
+
// Only needed for 3DS transactions but still helpful
|
101 |
+
vzero.setAmount('<?php echo Mage::getSingleton('checkout/cart')->getQuote()->collectTotals()->getGrandTotal(); ?>');
|
102 |
+
}
|
103 |
+
|
104 |
+
// Loop through each saved card being selected
|
105 |
+
$$('#creditcard-saved-accounts input[type="radio"]').each(function(elm) {
|
106 |
+
|
107 |
+
// Observe the elements changing
|
108 |
+
Element.observe(elm, 'change', function(event) {
|
109 |
+
|
110 |
+
// Has the user selected other?
|
111 |
+
if($$('#creditcard-saved-accounts input:checked[type=radio]').first().value == 'other') {
|
112 |
+
|
113 |
+
// Show the credit card form
|
114 |
+
$('credit-card-form').show();
|
115 |
+
|
116 |
+
// Enable the credit card form all the elements in the credit card form
|
117 |
+
$$('#credit-card-form input, #credit-card-form select').each(function(formElement) {
|
118 |
+
formElement.removeAttribute('disabled');
|
119 |
+
});
|
120 |
+
|
121 |
+
} else {
|
122 |
+
|
123 |
+
// Hide the new credit card form
|
124 |
+
$('credit-card-form').hide();
|
125 |
+
|
126 |
+
// Disable all the elements in the credit card form
|
127 |
+
$$('#credit-card-form input, #credit-card-form select').each(function(formElement) {
|
128 |
+
formElement.setAttribute('disabled', 'disabled');
|
129 |
+
});
|
130 |
+
|
131 |
+
}
|
132 |
+
});
|
133 |
+
});
|
134 |
+
|
135 |
+
</script>
|
app/design/adminhtml/default/default/template/gene/braintree/creditcard/info.phtml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="braintree_creditcard_logo" style="padding-top: 5px;padding-left: 2px;">
|
3 |
+
<img src="http://i.imgur.com/JR1BJTr.png" alt="<?php echo $this->__('PayPal - Braintree'); ?>" /> by <a href="http://gene.co.uk" target="_blank" style="text-decoration: none;">Gene Commerce</a>
|
4 |
+
</div>
|
5 |
+
|
6 |
+
<?php if ($_specificInfo = $this->getSpecificInformation()):?>
|
7 |
+
<table>
|
8 |
+
<?php foreach ($_specificInfo as $_label => $_value):?>
|
9 |
+
<tr>
|
10 |
+
<th width="220"><?php echo $this->escapeHtml($_label)?>:</td>
|
11 |
+
<td><?php echo nl2br(implode($this->getValueAsArray($_value, false), "\n"))?></td>
|
12 |
+
</tr>
|
13 |
+
<?php endforeach; ?>
|
14 |
+
</table>
|
15 |
+
<?php endif;?>
|
16 |
+
|
17 |
+
<?php echo $this->getChildHtml()?>
|
app/design/adminhtml/default/default/template/gene/braintree/js.phtml
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script type="text/javascript">
|
2 |
+
//<![CDATA[
|
3 |
+
// Pass some data over to vZero integration JS
|
4 |
+
var vzero = new vZero(
|
5 |
+
'gene_braintree_creditcard',
|
6 |
+
'<?php echo $this->getClientToken(); ?>',
|
7 |
+
false,
|
8 |
+
['order-billing_address_firstname', 'order-billing_address_lastname'],
|
9 |
+
['order-billing_address_postcode']
|
10 |
+
);
|
11 |
+
|
12 |
+
// Init the environment
|
13 |
+
vzero.init();
|
14 |
+
|
15 |
+
// Store the original payment method
|
16 |
+
var adminOrderOriginal = AdminOrder.prototype.submit;
|
17 |
+
|
18 |
+
// Intercept the save function
|
19 |
+
AdminOrder.prototype.submit = function() {
|
20 |
+
|
21 |
+
// Check we're using the braintree card method
|
22 |
+
if(order.paymentMethod == 'gene_braintree_creditcard') {
|
23 |
+
|
24 |
+
// Validate the form contents
|
25 |
+
if (editForm.validate()) {
|
26 |
+
|
27 |
+
// Store these to be used later on
|
28 |
+
var adminThis = this;
|
29 |
+
var adminArgs = arguments;
|
30 |
+
|
31 |
+
// Process the card
|
32 |
+
vzero.process({
|
33 |
+
onSuccess: function () {
|
34 |
+
|
35 |
+
// Disable the standard credit card form so the values don't get passed through to the checkout
|
36 |
+
$$('#payment_form_gene_braintree_creditcard input, #payment_form_gene_braintree_creditcard select').each(function (formElement) {
|
37 |
+
if (formElement.id != 'creditcard-payment-nonce' && formElement.getAttribute('data-genebraintree-name') != 'cvv' && formElement.id != 'gene_braintree_creditcard_store_in_vault' && formElement.id != 'device_data') {
|
38 |
+
formElement.setAttribute('disabled', 'disabled');
|
39 |
+
}
|
40 |
+
});
|
41 |
+
|
42 |
+
// Fire the original event and return the response
|
43 |
+
adminOrderResponse = adminOrderOriginal.apply(adminThis, adminArgs);
|
44 |
+
|
45 |
+
// Re-enable any form elements which were disabled
|
46 |
+
$$('#payment_form_gene_braintree_creditcard input, #payment_form_gene_braintree_creditcard select').each(function (formElement) {
|
47 |
+
formElement.removeAttribute('disabled');
|
48 |
+
});
|
49 |
+
|
50 |
+
// Run the original function
|
51 |
+
return adminOrderResponse;
|
52 |
+
|
53 |
+
}
|
54 |
+
});
|
55 |
+
}
|
56 |
+
|
57 |
+
} else {
|
58 |
+
return adminOrderOriginal.apply(this, arguments);
|
59 |
+
}
|
60 |
+
|
61 |
+
};
|
62 |
+
//]]>
|
63 |
+
</script>
|
app/design/adminhtml/default/default/template/gene/braintree/paypal/info.phtml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="braintree_paypal_logo" style="padding-top: 5px;padding-left: 2px;">
|
3 |
+
<img src="http://i.imgur.com/sitDbHA.png" alt="<?php echo $this->__('PayPal - Braintree'); ?>" /> by <a href="http://gene.co.uk" target="_blank" style="text-decoration: none;">Gene Commerce</a>
|
4 |
+
</div>
|
5 |
+
|
6 |
+
<?php if ($_specificInfo = $this->getSpecificInformation()):?>
|
7 |
+
<table>
|
8 |
+
<?php foreach ($_specificInfo as $_label => $_value):?>
|
9 |
+
<tr>
|
10 |
+
<th width="180"><?php echo $this->escapeHtml($_label)?>:</td>
|
11 |
+
<td><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n"))?></td>
|
12 |
+
</tr>
|
13 |
+
<?php endforeach; ?>
|
14 |
+
</table>
|
15 |
+
<?php endif;?>
|
16 |
+
|
17 |
+
<?php echo $this->getChildHtml()?>
|
app/design/adminhtml/default/default/template/gene/braintree/transactions/index.phtml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="content-header">
|
2 |
+
<table cellspacing="0">
|
3 |
+
<tr>
|
4 |
+
<td style="<?php echo $this->getHeaderWidth() ?>"><?php echo $this->getHeaderHtml() ?></td>
|
5 |
+
<td class="form-buttons"><?php echo $this->getButtonsHtml() ?></td>
|
6 |
+
</tr>
|
7 |
+
</table>
|
8 |
+
</div>
|
9 |
+
<?php echo $this->getChildHtml('search'); ?>
|
10 |
+
<div>
|
11 |
+
<?php echo $this->getGridHtml() ?>
|
12 |
+
</div>
|
app/design/adminhtml/default/default/template/gene/braintree/transactions/search.phtml
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<form action="" method="get">
|
2 |
+
<div class="switcher search">
|
3 |
+
|
4 |
+
<table>
|
5 |
+
<tr>
|
6 |
+
<th><label class="date_label" style="font-weight: bold;"><?php echo $this->__('Date Filter:') ?></label></th>
|
7 |
+
<td>
|
8 |
+
<span class="label"><?php echo $this->__('From:'); ?></span>
|
9 |
+
<img src="<?php echo $this->getSkinUrl('images/grid-cal.gif'); ?>" alt="" class="v-middle" id="gene_braintree_from_date_trig" title="Date selector">
|
10 |
+
<input type="text" name="from_date" id="gene_braintree_from_date" class="input-text no-changes" value="<?php echo $this->getFromDate(); ?>" size="14">
|
11 |
+
|
12 |
+
<span class="label"><?php echo $this->__('To:'); ?></span>
|
13 |
+
<img src="<?php echo $this->getSkinUrl('images/grid-cal.gif'); ?>" alt="" class="v-middle" id="gene_braintree_to_date_trig" title="Date selector">
|
14 |
+
<input type="text" name="to_date" id="gene_braintree_to_date" class="input-text no-changes" value="<?php echo $this->getToDate(); ?>" size="14">
|
15 |
+
</td>
|
16 |
+
</tr>
|
17 |
+
<tr>
|
18 |
+
<th><label style="font-weight: bold;" for="braintree_type"><?php echo $this->__('Type:') ?></label></th>
|
19 |
+
<td>
|
20 |
+
<select id="braintree_type" name="type">
|
21 |
+
<?php foreach($this->getTypesAsArray() as $key => $value): ?>
|
22 |
+
<option value="<?php echo $key; ?>"<?php echo ($this->getSelectedType() == $key ? ' selected="selected"' : ''); ?>><?php echo $value; ?></option>
|
23 |
+
<?php endforeach; ?>
|
24 |
+
</select>
|
25 |
+
</td>
|
26 |
+
</tr>
|
27 |
+
<tr>
|
28 |
+
<th><label style="font-weight: bold;" for="braintree_status"><?php echo $this->__('Status:') ?></label></th>
|
29 |
+
<td>
|
30 |
+
<select id="braintree_status" name="status">
|
31 |
+
<?php foreach($this->getStatusesAsArray() as $key => $value): ?>
|
32 |
+
<option value="<?php echo $key; ?>"<?php echo ($this->getSelectedStatus() == $key ? ' selected="selected"' : ''); ?>><?php echo $value; ?></option>
|
33 |
+
<?php endforeach; ?>
|
34 |
+
</select>
|
35 |
+
</td>
|
36 |
+
</tr>
|
37 |
+
<tr>
|
38 |
+
<th><label style="font-weight: bold;" for="braintree_order_id"><?php echo $this->__('Magento Order ID:') ?></label></th>
|
39 |
+
<td>
|
40 |
+
<input type="text" id="braintree_order_id" name="order_id" value="<?php echo $this->getOrderId(); ?>" class="input-text" />
|
41 |
+
</td>
|
42 |
+
</tr>
|
43 |
+
<tr>
|
44 |
+
<th colspan="2">
|
45 |
+
<button type="submit">Filter Transactions</button>
|
46 |
+
<button type="reset" onclick="window.location='<?php echo Mage::helper('adminhtml')->getUrl('*/*/*'); ?>';">Reset</button>
|
47 |
+
</th>
|
48 |
+
</tr>
|
49 |
+
</table>
|
50 |
+
</div>
|
51 |
+
</form>
|
52 |
+
|
53 |
+
<style type="text/css">
|
54 |
+
.switcher.search th, .switcher.search td {
|
55 |
+
padding: 4px 10px 4px 2px;
|
56 |
+
}
|
57 |
+
</style>
|
58 |
+
|
59 |
+
<!-- Include the Calender Javascript -->
|
60 |
+
<script type="text/javascript">
|
61 |
+
Calendar.setup({
|
62 |
+
inputField : "gene_braintree_from_date",
|
63 |
+
ifFormat : "%d-%m-%Y %H:%M",
|
64 |
+
button : "gene_braintree_from_date_trig",
|
65 |
+
align : "Bl",
|
66 |
+
singleClick : true,
|
67 |
+
showsTime: true
|
68 |
+
});
|
69 |
+
Calendar.setup({
|
70 |
+
inputField : "gene_braintree_to_date",
|
71 |
+
ifFormat : "%d-%m-%Y %H:%M",
|
72 |
+
button : "gene_braintree_to_date_trig",
|
73 |
+
align : "Bl",
|
74 |
+
singleClick : true,
|
75 |
+
showsTime: true
|
76 |
+
});
|
77 |
+
|
78 |
+
$("gene_braintree_from_date_trig").observe("click", showCalendar);
|
79 |
+
$("gene_braintree_to_date_trig").observe("click", showCalendar);
|
80 |
+
|
81 |
+
function showCalendar(event){
|
82 |
+
var element = event.element(event);
|
83 |
+
var offset = $(element).viewportOffset();
|
84 |
+
var scrollOffset = $(element).cumulativeScrollOffset();
|
85 |
+
var dimensionsButton = $(element).getDimensions();
|
86 |
+
var index = $("widget-chooser").getStyle("zIndex");
|
87 |
+
|
88 |
+
$$("div.calendar").each(function(item){
|
89 |
+
if ($(item).visible()) {
|
90 |
+
var dimensionsCalendar = $(item).getDimensions();
|
91 |
+
|
92 |
+
$(item).setStyle({
|
93 |
+
"zIndex" : index + 1,
|
94 |
+
"left" : offset[0] + scrollOffset[0] - dimensionsCalendar.width
|
95 |
+
+ dimensionsButton.width + "px",
|
96 |
+
"top" : offset[1] + scrollOffset[1] + dimensionsButton.height + "px"
|
97 |
+
});
|
98 |
+
};
|
99 |
+
});
|
100 |
+
};
|
101 |
+
</script>
|
app/design/frontend/base/default/layout/gene/braintree.xml
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
|
4 |
+
<checkout_onepage_index>
|
5 |
+
<reference name="head">
|
6 |
+
<action method="addJs"><file>gene/braintree/braintree.js</file></action>
|
7 |
+
<action method="addJs"><file>gene/braintree/vzero.js</file></action>
|
8 |
+
</reference>
|
9 |
+
<reference name="before_body_end">
|
10 |
+
<block type="gene_braintree/js" name="gene_braintree_setup" template="gene/braintree/js/setup.phtml" />
|
11 |
+
<block type="gene_braintree/js" name="gene_braintree_js" template="gene/braintree/js/default.phtml" />
|
12 |
+
|
13 |
+
<!-- Set the payment form ID for the fraud prevention -->
|
14 |
+
<block type="gene_braintree/js" name="gene_braintree_data" template="gene/braintree/js/data.phtml">
|
15 |
+
<action method="setData">
|
16 |
+
<key>payment_form_id</key>
|
17 |
+
<value>co-payment-form</value>
|
18 |
+
</action>
|
19 |
+
</block>
|
20 |
+
</reference>
|
21 |
+
</checkout_onepage_index>
|
22 |
+
|
23 |
+
<!-- We have to use a customized version of the js.phtml file for Amasty's checkout solution -->
|
24 |
+
<amasty_onestep_checkout>
|
25 |
+
<reference name="before_body_end">
|
26 |
+
<remove name="gene_braintree_js" />
|
27 |
+
<block type="gene_braintree/js" name="gene_braintree_amasty_js" template="gene/braintree/js/amasty.phtml" />
|
28 |
+
</reference>
|
29 |
+
</amasty_onestep_checkout>
|
30 |
+
|
31 |
+
<!-- Need to include the standard resources for the onestepcheckout.com solution -->
|
32 |
+
<onestepcheckout_index_index>
|
33 |
+
<reference name="head">
|
34 |
+
<action method="addJs"><file>gene/braintree/braintree.js</file></action>
|
35 |
+
<action method="addJs"><file>gene/braintree/vzero.js</file></action>
|
36 |
+
</reference>
|
37 |
+
<reference name="before_body_end">
|
38 |
+
<block type="gene_braintree/js" name="gene_braintree_setup" template="gene/braintree/js/setup.phtml" />
|
39 |
+
<block type="gene_braintree/js" name="gene_braintree_js" template="gene/braintree/js/idev.phtml" />
|
40 |
+
|
41 |
+
<!-- We include device data at the end of the larger form -->
|
42 |
+
<block type="gene_braintree/js" name="gene_braintree_data" template="gene/braintree/js/data.phtml">
|
43 |
+
<action method="setData">
|
44 |
+
<key>payment_form_id</key>
|
45 |
+
<value>onestepcheckout-form</value>
|
46 |
+
</action>
|
47 |
+
</block>
|
48 |
+
</reference>
|
49 |
+
</onestepcheckout_index_index>
|
50 |
+
|
51 |
+
<checkout_onepage_paymentmethod>
|
52 |
+
<reference name="root">
|
53 |
+
<block type="core/text_list" name="additional" as="additional">
|
54 |
+
<block type="gene_braintree/creditcard_threedsecure" name="gene_braintree_creditcard_threedsecure" template="gene/braintree/creditcard/threedsecure.phtml" />
|
55 |
+
</block>
|
56 |
+
</reference>
|
57 |
+
</checkout_onepage_paymentmethod>
|
58 |
+
|
59 |
+
<customer_account>
|
60 |
+
<reference name="customer_account_navigation">
|
61 |
+
<action method="addLink" translate="label" module="customer">
|
62 |
+
<name>braintree.saved</name>
|
63 |
+
<path>braintree/saved/index</path>
|
64 |
+
<label>Saved Payment Information</label>
|
65 |
+
</action>
|
66 |
+
</reference>
|
67 |
+
</customer_account>
|
68 |
+
|
69 |
+
<braintree_saved_index translate="label">
|
70 |
+
<label>Saved Payment Information</label>
|
71 |
+
<update handle="customer_account"/>
|
72 |
+
<!-- Mage_Customer -->
|
73 |
+
<reference name="root">
|
74 |
+
<action method="setTemplate"><template>page/2columns-left.phtml</template></action>
|
75 |
+
</reference>
|
76 |
+
<reference name="my.account.wrapper">
|
77 |
+
<block type="gene_braintree/saved" name="gene_braintree_saved_payments" template="gene/braintree/customer/saved.phtml">
|
78 |
+
<block type="gene_braintree/saved" name="gene_braintree_saved_payments_method" as="methods" template="gene/braintree/customer/methods.phtml" />
|
79 |
+
</block>
|
80 |
+
</reference>
|
81 |
+
</braintree_saved_index>
|
82 |
+
|
83 |
+
</layout>
|
app/design/frontend/base/default/template/gene/braintree/creditcard.phtml
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/* @var $this Gene_Braintree_Block_Creditcard */
|
3 |
+
$_code = $this->getMethodCode()
|
4 |
+
?>
|
5 |
+
<div id="payment_form_<?php echo $_code ?>" style="display:none;" class="form-list">
|
6 |
+
|
7 |
+
<?php if($this->hasSavedDetails() && $this->getMethod()->isVaultEnabled()): ?>
|
8 |
+
|
9 |
+
<label><?php echo $this->__('Saved Cards'); ?></label>
|
10 |
+
<p><?php echo $this->__('The following credit cards accounts are currently linked with your account.'); ?></p>
|
11 |
+
<table cellspacing="0" cellpadding="0" id="creditcard-saved-accounts">
|
12 |
+
<?php
|
13 |
+
$count = 0;
|
14 |
+
foreach($this->getSavedDetails() as $savedDetail):
|
15 |
+
?>
|
16 |
+
<tr>
|
17 |
+
<td width="20">
|
18 |
+
<?php if($this->getMethod()->is3DEnabled()): ?>
|
19 |
+
<input type="radio" name="payment[card_payment_method_token]" id="<?php echo $savedDetail->token; ?>" data-token="<?php echo $savedDetail->token; ?>" data-threedsecure-nonce="<?php echo $this->getMethod()->getThreeDSecureVaultNonce($savedDetail->token); ?>" value="threedsecure"<?php echo ($count == 0 ? ' checked="checked"' : ''); ?>/>
|
20 |
+
<?php else: ?>
|
21 |
+
<input type="radio" name="payment[card_payment_method_token]" id="<?php echo $savedDetail->token; ?>" value="<?php echo $savedDetail->token; ?>"<?php echo ($count == 0 ? ' checked="checked"' : ''); ?>/>
|
22 |
+
<?php endif; ?>
|
23 |
+
</td>
|
24 |
+
<td valign="middle">
|
25 |
+
<label for="<?php echo $savedDetail->token; ?>" style="line-height: 48px;">
|
26 |
+
<img src="<?php echo $this->getSkinUrl('images/gene/braintree/' . $this->getCardIcon($savedDetail->cardType)) ?>" align="left" /> xxxx - xxxx - xxxx - <?php echo $savedDetail->last4; ?> <em><?php echo $this->__('Expires:'); ?></em> <?php echo $savedDetail->expirationMonth; ?>/<?php echo $savedDetail->expirationYear; ?>
|
27 |
+
</label>
|
28 |
+
</td>
|
29 |
+
</tr>
|
30 |
+
<?php
|
31 |
+
++$count;
|
32 |
+
endforeach; ?>
|
33 |
+
<tr>
|
34 |
+
<td width="20"><input type="radio" name="payment[card_payment_method_token]" id="other-creditcard" value="other" /></td>
|
35 |
+
<td><label for="other-creditcard"><?php echo $this->__('New Credit Card'); ?></label></td>
|
36 |
+
</tr>
|
37 |
+
</table>
|
38 |
+
|
39 |
+
<?php endif; ?>
|
40 |
+
|
41 |
+
<div id="credit-card-form"<?php echo ($this->hasSavedDetails() && $this->getMethod()->isVaultEnabled() ? ' style="display: none;"' : ''); ?>>
|
42 |
+
<ul class="form-list">
|
43 |
+
<li>
|
44 |
+
<label for="<?php echo $_code ?>_cc_number" class="required"><em>*</em><?php echo $this->__('Credit Card Number') ?></label>
|
45 |
+
<div class="input-box card-number">
|
46 |
+
<input type="text" data-genebraintree-name="number" name="payment[cc_number]" id="<?php echo $_code ?>_cc_number" title="<?php echo $this->__('Credit Card Number') ?>" class="input-text validate-cc-number validate-cc-type validate-accepted-type" value=""/>
|
47 |
+
|
48 |
+
<div class="card-type"><img src="<?php echo $this->getSkinUrl('images/gene/braintree/card.png') ?>" id="card-type-image" /></div>
|
49 |
+
</div>
|
50 |
+
</li>
|
51 |
+
<li id="<?php echo $_code ?>_cc_type_exp_div">
|
52 |
+
<label for="<?php echo $_code ?>_expiration" class="required"><em>*</em><?php echo $this->__('Expiration Date') ?></label>
|
53 |
+
<div class="input-box">
|
54 |
+
<div class="v-fix">
|
55 |
+
<select id="<?php echo $_code ?>_expiration" name="payment[cc_exp_month]" data-genebraintree-name="expiration_month" class="month validate-cc-exp required-entry">
|
56 |
+
<?php $_ccExpMonth = $this->getInfoData('cc_exp_month') ?>
|
57 |
+
<?php foreach ($this->getCcMonths() as $k=>$v): ?>
|
58 |
+
<option value="<?php echo $k?$k:'' ?>"<?php if($k==$_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
|
59 |
+
<?php endforeach ?>
|
60 |
+
</select>
|
61 |
+
</div>
|
62 |
+
<div class="v-fix">
|
63 |
+
<?php $_ccExpYear = $this->getInfoData('cc_exp_year') ?>
|
64 |
+
<select id="<?php echo $_code ?>_expiration_yr" name="payment[cc_exp_year]" data-genebraintree-name="expiration_year" class="year required-entry">
|
65 |
+
<?php foreach ($this->getCcYears() as $k=>$v): ?>
|
66 |
+
<option value="<?php echo $k?$k:'' ?>"<?php if($k==$_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
|
67 |
+
<?php endforeach ?>
|
68 |
+
</select>
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
</li>
|
72 |
+
<?php echo $this->getChildHtml() ?>
|
73 |
+
<?php if($this->hasVerification()): ?>
|
74 |
+
<li id="<?php echo $_code ?>_cc_type_cvv_div">
|
75 |
+
<label for="<?php echo $_code ?>_cc_cid" class="required"><em>*</em><?php echo $this->__('Card Verification Number') ?></label>
|
76 |
+
<div class="input-box">
|
77 |
+
<div class="v-fix">
|
78 |
+
<input type="text" title="<?php echo $this->__('Card Verification Number') ?>" class="input-text cvv required-entry validate-cc-cvn" id="<?php echo $_code ?>_cc_cid" name="payment[cc_cid]" data-genebraintree-name="cvv" value="" />
|
79 |
+
</div>
|
80 |
+
<a href="#" class="cvv-what-is-this"><?php echo $this->__('What is this?') ?></a>
|
81 |
+
</div>
|
82 |
+
</li>
|
83 |
+
<?php endif; ?>
|
84 |
+
|
85 |
+
<?php if ($this->canSaveCard()): ?>
|
86 |
+
<li id="<?php echo $_code ?>_store_in_vault_div">
|
87 |
+
<input type="checkbox" title="<?php echo $this->__('Save this card for future use') ?>"
|
88 |
+
class="input-checkbox" id="<?php echo $_code ?>_store_in_vault" name="payment[save_card]"
|
89 |
+
value="1"/>
|
90 |
+
<label for="<?php echo $_code ?>_store_in_vault" style="float:none;"><?php echo $this->__(
|
91 |
+
'Save this card for future use'
|
92 |
+
) ?></label>
|
93 |
+
</li>
|
94 |
+
<?php endif; ?>
|
95 |
+
|
96 |
+
</ul>
|
97 |
+
|
98 |
+
<!-- Fields for the payment method -->
|
99 |
+
<input type="hidden" name="payment[payment_method_nonce]" id="creditcard-payment-nonce" />
|
100 |
+
|
101 |
+
<input type="hidden" id="<?php echo $_code ?>_cc_type" value="" />
|
102 |
+
</div>
|
103 |
+
|
104 |
+
</div>
|
105 |
+
|
106 |
+
<style type="text/css">
|
107 |
+
.card-number {
|
108 |
+
position: relative;
|
109 |
+
}
|
110 |
+
|
111 |
+
.card-type {
|
112 |
+
position: absolute;
|
113 |
+
top: 0;
|
114 |
+
left: 6px;
|
115 |
+
}
|
116 |
+
|
117 |
+
.card-number input {
|
118 |
+
height: 46px!important;
|
119 |
+
text-indent: 56px!important;
|
120 |
+
}
|
121 |
+
</style>
|
122 |
+
|
123 |
+
<script type="text/javascript">
|
124 |
+
//<![CDATA[
|
125 |
+
Validation.creditCartTypes = $H({
|
126 |
+
'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true],
|
127 |
+
'MC': [new RegExp('^5[1-5][0-9]{14}$'), new RegExp('^[0-9]{3}$'), true],
|
128 |
+
'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true],
|
129 |
+
'DI': [new RegExp('^6011[0-9]{12}$'), new RegExp('^[0-9]{3}$'), true],
|
130 |
+
'JCB': [new RegExp('^(3[0-9]{15}|(2131|1800)[0-9]{11})$'), new RegExp('^[0-9]{4}$'), true],
|
131 |
+
'OT': [false, new RegExp('^([0-9]{3}|[0-9]{4})?$'), false],
|
132 |
+
'ME': [new RegExp('^(?:5[0678][0-9]{2}|6304|6390|67[0-9]{2})[0-9]{8,15}$'), new RegExp('^[0-9]{3}$'), true]
|
133 |
+
});
|
134 |
+
//]]>
|
135 |
+
</script>
|
136 |
+
|
137 |
+
<!-- Attach an event onto all radio buttons -->
|
138 |
+
<script type="text/javascript">
|
139 |
+
|
140 |
+
// Set a flag to determine whether the PayPal flag is initialized
|
141 |
+
var CreditCardInit = false;
|
142 |
+
|
143 |
+
// Wrap our logic in a function so we can init in different ways
|
144 |
+
initCreditCard = function() {
|
145 |
+
|
146 |
+
// Verify that vzero is defined before attempting to use it
|
147 |
+
if (typeof vzero !== 'undefined') {
|
148 |
+
|
149 |
+
// Tell the system we're init
|
150 |
+
CreditCardInit = true;
|
151 |
+
|
152 |
+
// Always set the amount as it's needed within 3D secure requests
|
153 |
+
vzero.setAmount('<?php echo Mage::getSingleton('checkout/cart')->getQuote()->collectTotals()->getGrandTotal(); ?>');
|
154 |
+
|
155 |
+
// We now need to set this information into the browser
|
156 |
+
vzero.setBillingName("<?php echo $this->jsQuoteEscape(Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress()->getName(), '"'); ?>");
|
157 |
+
vzero.setBillingPostcode("<?php echo $this->jsQuoteEscape(Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress()->getPostcode(), '"'); ?>");
|
158 |
+
|
159 |
+
// Set the accepted cards
|
160 |
+
vzero.setAcceptedCards(<?php echo $this->getCcAvailableTypes(); ?>);
|
161 |
+
}
|
162 |
+
|
163 |
+
// Loop through each saved card being selected
|
164 |
+
$$('#creditcard-saved-accounts input[type="radio"]').each(function (elm) {
|
165 |
+
|
166 |
+
// Observe the elements changing
|
167 |
+
Element.observe(elm, 'change', function (event) {
|
168 |
+
|
169 |
+
// Has the user selected other?
|
170 |
+
if ($$('#creditcard-saved-accounts input:checked[type=radio]').first().value == 'other') {
|
171 |
+
|
172 |
+
// Show the credit card form
|
173 |
+
$('credit-card-form').show();
|
174 |
+
|
175 |
+
// Enable the credit card form all the elements in the credit card form
|
176 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
177 |
+
formElement.removeAttribute('disabled');
|
178 |
+
});
|
179 |
+
|
180 |
+
} else {
|
181 |
+
|
182 |
+
// Hide the new credit card form
|
183 |
+
$('credit-card-form').hide();
|
184 |
+
|
185 |
+
// Disable all the elements in the credit card form
|
186 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
187 |
+
formElement.setAttribute('disabled', 'disabled');
|
188 |
+
});
|
189 |
+
|
190 |
+
}
|
191 |
+
});
|
192 |
+
});
|
193 |
+
|
194 |
+
// Observe the card type
|
195 |
+
if(typeof vzero !== "undefined") {
|
196 |
+
vzero.observeCardType();
|
197 |
+
}
|
198 |
+
|
199 |
+
};
|
200 |
+
|
201 |
+
// Load up credit card
|
202 |
+
initCreditCard();
|
203 |
+
|
204 |
+
// If the function didn't run on the load of the payment method do it on dom:loaded
|
205 |
+
if(!CreditCardInit) {
|
206 |
+
document.observe('dom:loaded', function () {
|
207 |
+
initCreditCard();
|
208 |
+
});
|
209 |
+
}
|
210 |
+
|
211 |
+
// Add our new validation type
|
212 |
+
Validation.add('validate-accepted-type', 'Sadly, we\'re unable to accept this type of card, please try another.', function(v) {
|
213 |
+
if($('<?php echo $_code ?>_cc_type') != undefined) {
|
214 |
+
if (vzero.getAcceptedCards().indexOf($('<?php echo $_code ?>_cc_type').value) == -1) {
|
215 |
+
return false;
|
216 |
+
}
|
217 |
+
}
|
218 |
+
return true;
|
219 |
+
});
|
220 |
+
|
221 |
+
// Update a couple of the messages
|
222 |
+
if(Validation.get('validate-cc-type') != undefined) {
|
223 |
+
Validation.get('validate-cc-type').error = "<?php echo $this->__('We cannot detect the card type for this card number, please try re-entering your card details.'); ?>";
|
224 |
+
}
|
225 |
+
if(Validation.get('validate-cc-number') != undefined) {
|
226 |
+
Validation.get('validate-cc-number').error = "<?php echo $this->__('We cannot match this card number to any of our accepted payment methods, please try re-entering your details.'); ?>"
|
227 |
+
}
|
228 |
+
</script>
|
app/design/frontend/base/default/template/gene/braintree/creditcard/info.phtml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<p><strong><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></strong></p>
|
2 |
+
|
3 |
+
<?php if ($_specificInfo = $this->getSpecificInformation()):?>
|
4 |
+
<table>
|
5 |
+
<tbody>
|
6 |
+
<?php foreach ($_specificInfo as $_label => $_value):
|
7 |
+
if($_value): ?>
|
8 |
+
<tr>
|
9 |
+
<th style="text-align: left;font-weight:bold;padding: 3px 0;"><?php echo $this->escapeHtml($_label)?>:</th>
|
10 |
+
</tr>
|
11 |
+
<tr>
|
12 |
+
<td style="padding: 3px 0;"><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n"))?></td>
|
13 |
+
</tr>
|
14 |
+
<?php endif;
|
15 |
+
endforeach; ?>
|
16 |
+
</tbody>
|
17 |
+
</table>
|
18 |
+
<?php endif;?>
|
19 |
+
|
20 |
+
<?php echo $this->getChildHtml()?>
|
app/design/frontend/base/default/template/gene/braintree/creditcard/threedsecure.phtml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<!-- 3D Secure Container -->
|
2 |
+
<div id="3dsecure_container"></div>
|
app/design/frontend/base/default/template/gene/braintree/customer/methods.phtml
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if($savedDetails = $this->getSavedDetails($this->getType())): ?>
|
2 |
+
|
3 |
+
<table width="100%">
|
4 |
+
<?php foreach($savedDetails as $savedDetail): ?>
|
5 |
+
<tr>
|
6 |
+
<td width="60">
|
7 |
+
<img src="<?php echo $this->getSkinUrl('images/gene/braintree/' . Gene_Braintree_Block_Creditcard::getCardIcon((isset($savedDetail->cardType) ? $savedDetail->cardType : 'paypal'))); ?>" />
|
8 |
+
</td>
|
9 |
+
<td>
|
10 |
+
<?php if(isset($savedDetail->cardType)): ?>
|
11 |
+
xxxx - xxxx - xxxx - <?php echo $savedDetail->last4; ?> <em><?php echo $this->__('Expires:'); ?></em> <?php echo $savedDetail->expirationMonth; ?>/<?php echo $savedDetail->expirationYear; ?>
|
12 |
+
<?php else: ?>
|
13 |
+
<?php echo $savedDetail->email; ?>
|
14 |
+
<?php endif; ?>
|
15 |
+
</td>
|
16 |
+
<td>
|
17 |
+
<a href="<?php echo $this->getUrl('*/*/remove', array('id' => $savedDetail->token)); ?>" onclick="if(!confirm('<?php echo $this->__('Are you sure you want to remove this payment method?'); ?>')) { return false }"><?php echo $this->__('Remove'); ?></a>
|
18 |
+
</td>
|
19 |
+
</tr>
|
20 |
+
<?php endforeach; ?>
|
21 |
+
</table>
|
22 |
+
|
23 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/gene/braintree/customer/saved.phtml
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="page-title">
|
2 |
+
<h1><?php echo $this->__('Saved Payment Information') ?></h1>
|
3 |
+
</div>
|
4 |
+
|
5 |
+
<?php echo $this->getMessagesBlock()->toHtml() ?>
|
6 |
+
|
7 |
+
<div class="fieldset">
|
8 |
+
|
9 |
+
<?php if($this->hasSavedDetails()): ?>
|
10 |
+
|
11 |
+
<p><?php echo $this->__('You\'re able to use any of the listed payment methods below when purchasing through our checkout, you\'re able to add new payment methods within the checkout.'); ?></p>
|
12 |
+
|
13 |
+
<div class="col2-set">
|
14 |
+
|
15 |
+
<?php if($this->hasSavedDetails(Gene_Braintree_Model_Saved::SAVED_CREDITCARD_ID)): ?>
|
16 |
+
<div class="col-1">
|
17 |
+
<h2 class="legend"><?php echo $this->__('Cards') ?></h2>
|
18 |
+
<?php echo $this->getChild('methods')->setType(Gene_Braintree_Model_Saved::SAVED_CREDITCARD_ID)->toHtml(); ?>
|
19 |
+
</div>
|
20 |
+
<?php endif; ?>
|
21 |
+
|
22 |
+
<?php if($this->hasSavedDetails(Gene_Braintree_Model_Saved::SAVED_PAYPAL_ID)): ?>
|
23 |
+
<div class="col-1">
|
24 |
+
<h2 class="legend"><?php echo $this->__('PayPal') ?></h2>
|
25 |
+
<?php echo $this->getChild('methods')->setType(Gene_Braintree_Model_Saved::SAVED_PAYPAL_ID)->toHtml(); ?>
|
26 |
+
</div>
|
27 |
+
<?php endif; ?>
|
28 |
+
|
29 |
+
</div>
|
30 |
+
|
31 |
+
<?php else: ?>
|
32 |
+
<p><?php echo $this->__('You currently have no saved payment information, you can save a payment method when making a purchase.'); ?></p>
|
33 |
+
<?php endif; ?>
|
34 |
+
</div>
|
app/design/frontend/base/default/template/gene/braintree/js/amasty.phtml
ADDED
@@ -0,0 +1,375 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Add in support for Amasty One Step Checkout
|
4 |
+
* https://amasty.com/single-step-checkout.html
|
5 |
+
*/
|
6 |
+
?>
|
7 |
+
<script type="text/javascript">
|
8 |
+
|
9 |
+
// Older versions of the checkout don't contain this variable
|
10 |
+
if(typeof checkoutRunning == 'undefined') {
|
11 |
+
var checkoutRunning = false;
|
12 |
+
}
|
13 |
+
|
14 |
+
// Check that we haven't already set the original complete checkout method
|
15 |
+
if(originalCompleteCheckout === undefined && completeCheckout !== undefined) {
|
16 |
+
|
17 |
+
// Store the old complete checkout function
|
18 |
+
var originalCompleteCheckout = completeCheckout;
|
19 |
+
|
20 |
+
// Re-define the original method so we can do some jazz with it
|
21 |
+
completeCheckout = function () {
|
22 |
+
|
23 |
+
// Device data should never be disabled
|
24 |
+
$('device_data').removeAttribute('disabled');
|
25 |
+
|
26 |
+
// Always attempt to update the card type on submission
|
27 |
+
if($$('[data-genebraintree-name="number"]').first() != undefined) {
|
28 |
+
vzero.updateCardType($$('[data-genebraintree-name="number"]').first().value);
|
29 |
+
}
|
30 |
+
|
31 |
+
// Run the original validation functions
|
32 |
+
if (amscheckoutForm.validator.validate() && !checkoutRunning) {
|
33 |
+
|
34 |
+
// Are we dealing with the credit card method?
|
35 |
+
if (payment.currentMethod == 'gene_braintree_creditcard') {
|
36 |
+
|
37 |
+
// Update the data as we're in a one step
|
38 |
+
vzero.updateData(function() {
|
39 |
+
|
40 |
+
// Grab these directly from the form and update
|
41 |
+
if ($('billing:firstname') != undefined && $('billing:lastname') != undefined) {
|
42 |
+
vzero.setBillingName($('billing:firstname').value + ' ' + $('billing:lastname').value);
|
43 |
+
}
|
44 |
+
if ($('billing:postcode') != undefined) {
|
45 |
+
vzero.setBillingPostcode($('billing:postcode').value);
|
46 |
+
}
|
47 |
+
|
48 |
+
// Check is running
|
49 |
+
checkoutRunning = true;
|
50 |
+
|
51 |
+
// Show the loading
|
52 |
+
showLoading();
|
53 |
+
|
54 |
+
// Process the card
|
55 |
+
vzero.process({
|
56 |
+
onSuccess: function () {
|
57 |
+
|
58 |
+
// Disable the standard credit card form so the values don't get passed through to the checkout
|
59 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
60 |
+
if (formElement.id != 'creditcard-payment-nonce' && formElement.getAttribute('data-genebraintree-name') != 'cvv' && formElement.id != 'gene_braintree_creditcard_store_in_vault' && formElement.id != 'device_data') {
|
61 |
+
formElement.setAttribute('disabled', 'disabled');
|
62 |
+
}
|
63 |
+
});
|
64 |
+
|
65 |
+
// No longer running
|
66 |
+
checkoutRunning = false;
|
67 |
+
|
68 |
+
// Fire the original event and return the response
|
69 |
+
completeCheckoutResponse = originalCompleteCheckout.apply(this, arguments);
|
70 |
+
|
71 |
+
// Re-enable any form elements which were disabled
|
72 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
73 |
+
formElement.removeAttribute('disabled');
|
74 |
+
});
|
75 |
+
|
76 |
+
// Run the original function
|
77 |
+
return completeCheckoutResponse;
|
78 |
+
},
|
79 |
+
onFailure: function() {
|
80 |
+
|
81 |
+
// Reset the waiting for the parent function
|
82 |
+
hideLoading();
|
83 |
+
|
84 |
+
// No longer running
|
85 |
+
checkoutRunning = false;
|
86 |
+
|
87 |
+
}
|
88 |
+
});
|
89 |
+
|
90 |
+
});
|
91 |
+
|
92 |
+
// We're updating data don't do anything else for now
|
93 |
+
return false;
|
94 |
+
|
95 |
+
}
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
// Stop further processing
|
100 |
+
return originalCompleteCheckout.apply(this, arguments);
|
101 |
+
};
|
102 |
+
}
|
103 |
+
|
104 |
+
// Only intercept the payment method once
|
105 |
+
if(paymentOriginal == undefined) {
|
106 |
+
|
107 |
+
// It's not been ran so set it to false
|
108 |
+
var PayPalCompleteRan = false;
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Function to run once PayPal has been completed
|
112 |
+
*/
|
113 |
+
completePayPal = function(obj) {
|
114 |
+
|
115 |
+
// Check the flag to make sure we're good to run the function
|
116 |
+
if(!PayPalCompleteRan) {
|
117 |
+
|
118 |
+
// Mark the flag as true
|
119 |
+
PayPalCompleteRan = true;
|
120 |
+
|
121 |
+
// Force check
|
122 |
+
payment.switchMethod('gene_braintree_paypal', true);
|
123 |
+
|
124 |
+
// Re-enable the form
|
125 |
+
$('paypal-payment-nonce').removeAttribute('disabled');
|
126 |
+
$('paypal-payment-nonce').value = obj.nonce;
|
127 |
+
|
128 |
+
// Show the button again
|
129 |
+
hidePayPalButton();
|
130 |
+
|
131 |
+
// No longer running
|
132 |
+
checkoutRunning = false;
|
133 |
+
|
134 |
+
// Show the loading thing
|
135 |
+
showLoading();
|
136 |
+
|
137 |
+
// Run the complete checkout method
|
138 |
+
return completeCheckout();
|
139 |
+
|
140 |
+
}
|
141 |
+
|
142 |
+
};
|
143 |
+
|
144 |
+
// Flag to check if the PayPal button is already loading
|
145 |
+
var PayPalButtonLoading = false;
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Easily add the PayPal button into the DOM
|
149 |
+
*/
|
150 |
+
addPayPalButton = function() {
|
151 |
+
|
152 |
+
// Check we can locate the submit button
|
153 |
+
if($$('.amscheckout-submit').first() != undefined && $('paypal-complete') == undefined && PayPalButtonLoading == false) {
|
154 |
+
|
155 |
+
// The button is loading
|
156 |
+
PayPalButtonLoading = true;
|
157 |
+
|
158 |
+
// As the PayPal button has to request data from the server show the loader
|
159 |
+
showLoading();
|
160 |
+
|
161 |
+
// Update the data contained within the classes
|
162 |
+
vzero.updateData(function () {
|
163 |
+
|
164 |
+
// The button is no longer loading
|
165 |
+
PayPalButtonLoading = false;
|
166 |
+
|
167 |
+
// Hide it once we're done
|
168 |
+
hideLoading();
|
169 |
+
|
170 |
+
// Validate the payment method is still correct
|
171 |
+
if(payment.currentMethod == 'gene_braintree_paypal' && $('paypal-complete') == undefined) {
|
172 |
+
|
173 |
+
// Set the flag to false as we've created a new button
|
174 |
+
PayPalCompleteRan = false;
|
175 |
+
|
176 |
+
// Hide the submit button
|
177 |
+
$$('.amscheckout-submit').first().hide();
|
178 |
+
|
179 |
+
// Add in our PayPal button
|
180 |
+
$$('.amscheckout-submit').first().up().insert('<div id="paypal-complete"><label id="paypal-label"><?php echo $this->__('Complete checkout with'); ?> </label><div id="paypal-container"></div></div>');
|
181 |
+
|
182 |
+
// Always stop the window from opening
|
183 |
+
$('paypal-complete').observe('click', function(event) {
|
184 |
+
|
185 |
+
// Validate the form before we open the PayPal modal window
|
186 |
+
if (!amscheckoutForm.validator.validate() || checkoutRunning) {
|
187 |
+
|
188 |
+
// Sadly we're unable to intercept the PayPal window in any other way then just hard closing it
|
189 |
+
vzeroPaypal.closePayPalWindow();
|
190 |
+
}
|
191 |
+
});
|
192 |
+
|
193 |
+
// Add in the PayPal button
|
194 |
+
vzeroPaypal.addPayPalButton({
|
195 |
+
onSuccess: completePayPal
|
196 |
+
});
|
197 |
+
|
198 |
+
}
|
199 |
+
|
200 |
+
});
|
201 |
+
|
202 |
+
} else if($('paypal-complete') != undefined) {
|
203 |
+
|
204 |
+
// The button is loading
|
205 |
+
PayPalButtonLoading = true;
|
206 |
+
|
207 |
+
// As the PayPal button has to request data from the server show the loader
|
208 |
+
showLoading();
|
209 |
+
|
210 |
+
// Update the data contained within the classes
|
211 |
+
vzero.updateData(function () {
|
212 |
+
|
213 |
+
// The button is no longer loading
|
214 |
+
PayPalButtonLoading = false;
|
215 |
+
|
216 |
+
// Hide it once we're done
|
217 |
+
hideLoading();
|
218 |
+
|
219 |
+
// Validate the payment method is still correct
|
220 |
+
if(payment.currentMethod == 'gene_braintree_paypal') {
|
221 |
+
|
222 |
+
// Set the flag to false as we've created a new button
|
223 |
+
PayPalCompleteRan = false;
|
224 |
+
|
225 |
+
// Hide the submit button
|
226 |
+
$$('.amscheckout-submit').first().hide();
|
227 |
+
|
228 |
+
// Add in the PayPal button
|
229 |
+
$('paypal-complete').show();
|
230 |
+
|
231 |
+
}
|
232 |
+
|
233 |
+
});
|
234 |
+
|
235 |
+
}
|
236 |
+
|
237 |
+
};
|
238 |
+
|
239 |
+
/**
|
240 |
+
* As we need to remove the PayPal button in multiple places
|
241 |
+
*/
|
242 |
+
hidePayPalButton = function() {
|
243 |
+
|
244 |
+
// If the user has selected a different payment method make some modifications
|
245 |
+
if($$('.amscheckout-submit').first() != undefined) {
|
246 |
+
$$('.amscheckout-submit').first().show();
|
247 |
+
}
|
248 |
+
|
249 |
+
// Remove the PayPal element
|
250 |
+
if($('paypal-complete') != undefined) {
|
251 |
+
$('paypal-complete').hide();
|
252 |
+
}
|
253 |
+
|
254 |
+
};
|
255 |
+
|
256 |
+
// Check if the payment method is the default
|
257 |
+
if(payment !== undefined) {
|
258 |
+
if((payment.currentMethod == 'gene_braintree_paypal' && $('paypal-saved-accounts') == undefined) || ($$('#paypal-saved-accounts input:checked[type=radio]').first() != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other')) {
|
259 |
+
|
260 |
+
// Verify that vzero is defined before attempting to use it
|
261 |
+
if(typeof vzeroPaypal !== 'undefined') {
|
262 |
+
|
263 |
+
// Always set the amount as it's needed within 3D secure requests
|
264 |
+
vzeroPaypal.setPricing('<?php echo Mage::getSingleton('checkout/cart')->getQuote()->collectTotals()->getGrandTotal(); ?>', '<?php echo Mage::getSingleton('checkout/cart')->getQuote()->getBaseCurrencyCode(); ?>');
|
265 |
+
}
|
266 |
+
|
267 |
+
addPayPalButton();
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
// Store the original payment method
|
272 |
+
var paymentOriginal = Payment.prototype.switchMethod;
|
273 |
+
|
274 |
+
// Intercept the save function
|
275 |
+
Payment.prototype.switchMethod = function (method) {
|
276 |
+
|
277 |
+
// Make sure the paypal complete action hasn't just ran
|
278 |
+
if(PayPalCompleteRan != true) {
|
279 |
+
|
280 |
+
// Detect PayPal choice
|
281 |
+
if (method == 'gene_braintree_paypal') {
|
282 |
+
|
283 |
+
if ($('paypal-saved-accounts') == undefined) {
|
284 |
+
addPayPalButton();
|
285 |
+
} else if ($('paypal-saved-accounts') != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first() != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other') {
|
286 |
+
addPayPalButton();
|
287 |
+
} else {
|
288 |
+
hidePayPalButton();
|
289 |
+
}
|
290 |
+
|
291 |
+
} else {
|
292 |
+
hidePayPalButton();
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
|
297 |
+
// Run the original function
|
298 |
+
return paymentOriginal.apply(this, arguments);
|
299 |
+
|
300 |
+
};
|
301 |
+
|
302 |
+
// If we have any saved accounts we'll need to do something jammy
|
303 |
+
if($$('#paypal-saved-accounts input[type=radio]').first() != undefined) {
|
304 |
+
|
305 |
+
// Loop through each radio button
|
306 |
+
$$('#paypal-saved-accounts input[type=radio]').each(function (savedAccount) {
|
307 |
+
|
308 |
+
// Observe them changing
|
309 |
+
Event.observe(savedAccount, 'click', function (ele) {
|
310 |
+
if(savedAccount.value == 'other') {
|
311 |
+
addPayPalButton();
|
312 |
+
} else {
|
313 |
+
hidePayPalButton();
|
314 |
+
}
|
315 |
+
});
|
316 |
+
});
|
317 |
+
}
|
318 |
+
|
319 |
+
var updateCheckoutOriginal = updateCheckout;
|
320 |
+
updateCheckout = function() {
|
321 |
+
|
322 |
+
// If we're updating the checkout remove the PayPal button
|
323 |
+
hidePayPalButton();
|
324 |
+
|
325 |
+
// Run the original function
|
326 |
+
return updateCheckoutOriginal.apply(this, arguments);
|
327 |
+
};
|
328 |
+
|
329 |
+
// What should happen if the user closes the 3D secure window?
|
330 |
+
vzero.close3dSecureMethod(function() {
|
331 |
+
|
332 |
+
// Hide the loading
|
333 |
+
hideLoading();
|
334 |
+
|
335 |
+
// Check is running
|
336 |
+
checkoutRunning = false;
|
337 |
+
|
338 |
+
});
|
339 |
+
|
340 |
+
// Observe the card type here as it'll fail within creditCard.phtml
|
341 |
+
vzero.observeCardType();
|
342 |
+
|
343 |
+
// Observe all Ajax requests for changes
|
344 |
+
vzero.observeAjaxRequests(function() {
|
345 |
+
|
346 |
+
// If the method is PayPal remove and re-add the PayPal button
|
347 |
+
if(payment.currentMethod == 'gene_braintree_paypal') {
|
348 |
+
hidePayPalButton();
|
349 |
+
addPayPalButton();
|
350 |
+
} else {
|
351 |
+
vzero.updateData();
|
352 |
+
}
|
353 |
+
|
354 |
+
});
|
355 |
+
|
356 |
+
}
|
357 |
+
</script>
|
358 |
+
<style type="text/css">
|
359 |
+
#paypal-label {
|
360 |
+
line-height: 44px;
|
361 |
+
float: left;
|
362 |
+
margin-right: 12px;
|
363 |
+
}
|
364 |
+
#braintree-paypal-button {
|
365 |
+
line-height: unset;
|
366 |
+
padding: 0;
|
367 |
+
float: left;
|
368 |
+
}
|
369 |
+
#braintree-paypal-loggedin {
|
370 |
+
display: none!important;
|
371 |
+
}
|
372 |
+
#braintree-paypal-loggedout {
|
373 |
+
display: block!important;
|
374 |
+
}
|
375 |
+
</style>
|
app/design/frontend/base/default/template/gene/braintree/js/data.phtml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Include the crucial braintree-data.js for fraud protection
|
4 |
+
*/
|
5 |
+
?>
|
6 |
+
<script src="https://js.braintreegateway.com/v1/braintree-data.js"></script>
|
7 |
+
<script>
|
8 |
+
<?php if($kountId = Mage::getStoreConfig('payment/gene_braintree_creditcard/kount_merchant_id')): ?>
|
9 |
+
var env = BraintreeData.environments.production.withId("<?php echo $kountId; ?>");
|
10 |
+
<?php else: ?>
|
11 |
+
var env = BraintreeData.environments.<?php echo Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_ENVIRONMENT_PATH); ?>;
|
12 |
+
<?php endif; ?>
|
13 |
+
BraintreeData.setup("<?php echo Mage::getStoreConfig(Gene_Braintree_Model_Wrapper_Braintree::BRAINTREE_MERCHANT_ID_PATH); ?>", '<?php echo ($this->getPaymentFormId() ? $this->getPaymentFormId() : 'co-payment-form'); ?>', env);
|
14 |
+
</script>
|
15 |
+
|
app/design/frontend/base/default/template/gene/braintree/js/default.phtml
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Intercept various functions for the default checkout flow
|
4 |
+
*/
|
5 |
+
?>
|
6 |
+
<script type="text/javascript">
|
7 |
+
|
8 |
+
// Store the current paymentMethod
|
9 |
+
var paymentMethod = false;
|
10 |
+
|
11 |
+
// Store the original payment method
|
12 |
+
var paymentOriginal = Payment.prototype.save;
|
13 |
+
|
14 |
+
// Intercept the save function
|
15 |
+
Payment.prototype.save = function() {
|
16 |
+
|
17 |
+
if (checkout.loadWaiting != false) return;
|
18 |
+
|
19 |
+
// Update our paymentMethod
|
20 |
+
paymentMethod = this.currentMethod;
|
21 |
+
|
22 |
+
// Check we're dealing with the current method
|
23 |
+
if (paymentMethod == 'gene_braintree_creditcard') {
|
24 |
+
|
25 |
+
// Always attempt to update the card type on submission
|
26 |
+
if($$('[data-genebraintree-name="number"]').first() != undefined) {
|
27 |
+
vzero.updateCardType($$('[data-genebraintree-name="number"]').first().value);
|
28 |
+
}
|
29 |
+
|
30 |
+
// Set the payment to loading
|
31 |
+
checkout.setLoadWaiting('payment');
|
32 |
+
|
33 |
+
// Do the standard validation
|
34 |
+
var validator = new Validation(this.form);
|
35 |
+
if (this.validate() && validator.validate()) {
|
36 |
+
|
37 |
+
// Store these to be used later on
|
38 |
+
var paymentThis = this;
|
39 |
+
var paymentArgs = arguments;
|
40 |
+
|
41 |
+
// Process the card
|
42 |
+
vzero.process({
|
43 |
+
onSuccess: function () {
|
44 |
+
|
45 |
+
// Reset the waiting for the parent function
|
46 |
+
checkout.setLoadWaiting(false);
|
47 |
+
|
48 |
+
// Disable the standard credit card form so the values don't get passed through to the checkout
|
49 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
50 |
+
if (formElement.id != 'creditcard-payment-nonce' && formElement.getAttribute('data-genebraintree-name') != 'cvv' && formElement.id != 'gene_braintree_creditcard_store_in_vault' && formElement.id != 'device_data') {
|
51 |
+
formElement.setAttribute('disabled', 'disabled');
|
52 |
+
}
|
53 |
+
});
|
54 |
+
|
55 |
+
// Fire the original event and return the response
|
56 |
+
paymentResponse = paymentOriginal.apply(paymentThis, paymentArgs);
|
57 |
+
|
58 |
+
// Re-enable any form elements which were disabled
|
59 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
60 |
+
formElement.removeAttribute('disabled');
|
61 |
+
});
|
62 |
+
|
63 |
+
// Run the original function
|
64 |
+
return paymentResponse;
|
65 |
+
},
|
66 |
+
onFailure: function() {
|
67 |
+
checkout.setLoadWaiting(false);
|
68 |
+
}
|
69 |
+
});
|
70 |
+
} else {
|
71 |
+
checkout.setLoadWaiting(false);
|
72 |
+
}
|
73 |
+
|
74 |
+
} else {
|
75 |
+
// Proxy the function through
|
76 |
+
return paymentOriginal.apply(this, arguments);
|
77 |
+
}
|
78 |
+
};
|
79 |
+
|
80 |
+
// Store the original payment method
|
81 |
+
var reviewInitOriginal = Review.prototype.initialize;
|
82 |
+
|
83 |
+
// Intercept the save function
|
84 |
+
Review.prototype.initialize = function(saveUrl, successUrl, agreementsForm) {
|
85 |
+
|
86 |
+
// Do the original action
|
87 |
+
var reviewResponse = reviewInitOriginal.apply(this, arguments);
|
88 |
+
|
89 |
+
// Swap out the buttons
|
90 |
+
if((paymentMethod == 'gene_braintree_paypal' && $('paypal-saved-accounts') == undefined) || ($$('#paypal-saved-accounts input:checked[type=radio]').first() != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other')) {
|
91 |
+
|
92 |
+
// Hide the checkout button
|
93 |
+
if ($$('#review-buttons-container button').first() != undefined) {
|
94 |
+
$$('#review-buttons-container button').first().hide();
|
95 |
+
}
|
96 |
+
|
97 |
+
// Insert out PayPal button
|
98 |
+
$('review-buttons-container').insert('<div id="paypal-complete"><label id="paypal-label"><?php echo $this->__('Complete checkout with'); ?> </label><div id="paypal-container"></div></div>');
|
99 |
+
|
100 |
+
// Add in the PayPal button
|
101 |
+
vzeroPaypal.addPayPalButton();
|
102 |
+
|
103 |
+
// Style the label nicely
|
104 |
+
$('paypal-label').setStyle({
|
105 |
+
'lineHeight': '44px',
|
106 |
+
'float': 'left',
|
107 |
+
'marginRight': '12px'
|
108 |
+
});
|
109 |
+
|
110 |
+
// If this button exists swap some minor styling things
|
111 |
+
if($('braintree-paypal-button') != undefined) {
|
112 |
+
|
113 |
+
// Fix some styling issues where we're placing the button
|
114 |
+
$('braintree-paypal-button').setStyle({
|
115 |
+
'lineHeight': 'auto',
|
116 |
+
'padding': '0',
|
117 |
+
'float': 'left'
|
118 |
+
});
|
119 |
+
}
|
120 |
+
|
121 |
+
} else {
|
122 |
+
|
123 |
+
// Revert our madness
|
124 |
+
if ($$('#review-buttons-container button').first() != undefined) {
|
125 |
+
$$('#review-buttons-container button').first().show();
|
126 |
+
}
|
127 |
+
|
128 |
+
// Remove the PayPal element
|
129 |
+
if($$('#paypal-complete').first() != undefined) {
|
130 |
+
$('paypal-complete').remove();
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
// If we're using braintree credit card disable the form on submission
|
135 |
+
if (paymentMethod == 'gene_braintree_creditcard') {
|
136 |
+
|
137 |
+
// Re-enable the form elements just in case something went wrong
|
138 |
+
$$('#credit-card-form input, #credit-card-form select').each(function(formElement) {
|
139 |
+
formElement.removeAttribute('disabled');
|
140 |
+
});
|
141 |
+
}
|
142 |
+
|
143 |
+
// Return the normal response
|
144 |
+
return reviewResponse;
|
145 |
+
|
146 |
+
};
|
147 |
+
|
148 |
+
// Store the original payment method
|
149 |
+
var reviewSaveOriginal = Review.prototype.save;
|
150 |
+
|
151 |
+
// Intercept the save function
|
152 |
+
Review.prototype.save = function() {
|
153 |
+
|
154 |
+
// If we're using braintree credit card disable the form on submission
|
155 |
+
if (paymentMethod == 'gene_braintree_creditcard') {
|
156 |
+
|
157 |
+
// Disable the standard credit card form so the values don't get passed through to the checkout
|
158 |
+
$$('#credit-card-form input, #credit-card-form select').each(function(formElement) {
|
159 |
+
if(formElement.id != 'creditcard-payment-nonce' && formElement.getAttribute('data-genebraintree-name') != 'cvv' && formElement.id != 'gene_braintree_creditcard_store_in_vault' && formElement.id != 'device_data') {
|
160 |
+
formElement.setAttribute('disabled', 'disabled');
|
161 |
+
}
|
162 |
+
});
|
163 |
+
}
|
164 |
+
|
165 |
+
// Do the original action
|
166 |
+
var reviewSaveResponse = reviewSaveOriginal.apply(this, arguments);
|
167 |
+
|
168 |
+
// If we're using braintree credit card disable the form on submission
|
169 |
+
if (paymentMethod == 'gene_braintree_creditcard') {
|
170 |
+
|
171 |
+
// Re-enable the form elements just in case something went wrong
|
172 |
+
$$('#credit-card-form input, #credit-card-form select').each(function(formElement) {
|
173 |
+
formElement.removeAttribute('disabled');
|
174 |
+
});
|
175 |
+
}
|
176 |
+
|
177 |
+
return reviewSaveResponse;
|
178 |
+
};
|
179 |
+
|
180 |
+
vzero.close3dSecureMethod(function() {
|
181 |
+
|
182 |
+
// Re-tokenize all the saved cards
|
183 |
+
vzero.tokenize3dSavedCards(function() {
|
184 |
+
checkout.setLoadWaiting(false);
|
185 |
+
});
|
186 |
+
|
187 |
+
});
|
188 |
+
</script>
|
app/design/frontend/base/default/template/gene/braintree/js/idev.phtml
ADDED
@@ -0,0 +1,402 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Add in support for onestepcheckout.com
|
4 |
+
* http://onestepcheckout.com
|
5 |
+
*/
|
6 |
+
?>
|
7 |
+
<script type="text/javascript">
|
8 |
+
|
9 |
+
// Flag to skip over our interception if needed
|
10 |
+
var processedVZero = false;
|
11 |
+
|
12 |
+
// Hook onto the event that submits the entire form
|
13 |
+
// Apparently there may be more than one of these buttons
|
14 |
+
$$('.onestepcheckout-place-order').each(function(elem){
|
15 |
+
|
16 |
+
// Observe the click event
|
17 |
+
elem.observe('click', function(e) {
|
18 |
+
|
19 |
+
// Device data should never be disabled
|
20 |
+
if($('device_data') != undefined) {
|
21 |
+
$('device_data').removeAttribute('disabled');
|
22 |
+
}
|
23 |
+
|
24 |
+
// Check to see if we've already processed the form?
|
25 |
+
if(!processedVZero) {
|
26 |
+
|
27 |
+
// Always attempt to update the card type on submission
|
28 |
+
if($$('[data-genebraintree-name="number"]').first() != undefined) {
|
29 |
+
vzero.updateCardType($$('[data-genebraintree-name="number"]').first().value);
|
30 |
+
}
|
31 |
+
|
32 |
+
// First validate the form
|
33 |
+
var form = new VarienForm('onestepcheckout-form');
|
34 |
+
|
35 |
+
// Validate the form like the parent method
|
36 |
+
if(!form.validator.validate()) {
|
37 |
+
|
38 |
+
// We want to stop any further events
|
39 |
+
Event.stop(e);
|
40 |
+
|
41 |
+
} else {
|
42 |
+
|
43 |
+
// Are we dealing with the credit card method?
|
44 |
+
if (payment.currentMethod == 'gene_braintree_creditcard') {
|
45 |
+
|
46 |
+
// Set this flag to stop the other function from firing
|
47 |
+
already_placing_order = true;
|
48 |
+
|
49 |
+
startLoading();
|
50 |
+
|
51 |
+
// Update the data as we're in a one step
|
52 |
+
vzero.updateData(function() {
|
53 |
+
|
54 |
+
// Grab these directly from the form and update
|
55 |
+
if ($('billing:firstname') != undefined && $('billing:lastname') != undefined) {
|
56 |
+
vzero.setBillingName($('billing:firstname').value + ' ' + $('billing:lastname').value);
|
57 |
+
}
|
58 |
+
if ($('billing:postcode') != undefined) {
|
59 |
+
vzero.setBillingPostcode($('billing:postcode').value);
|
60 |
+
}
|
61 |
+
|
62 |
+
// Process the card
|
63 |
+
vzero.process({
|
64 |
+
onSuccess: function () {
|
65 |
+
|
66 |
+
// Disable the standard credit card form so the values don't get passed through to the checkout
|
67 |
+
$$('#credit-card-form input, #credit-card-form select').each(function (formElement) {
|
68 |
+
if (formElement.id != 'creditcard-payment-nonce' && formElement.getAttribute('data-genebraintree-name') != 'cvv' && formElement.id != 'gene_braintree_creditcard_store_in_vault' && formElement.id != 'device_data') {
|
69 |
+
formElement.setAttribute('disabled', 'disabled');
|
70 |
+
}
|
71 |
+
});
|
72 |
+
|
73 |
+
stopLoading();
|
74 |
+
|
75 |
+
// Set the flag to true
|
76 |
+
processedVZero = true;
|
77 |
+
|
78 |
+
// We're no longer stopping the events
|
79 |
+
already_placing_order = false;
|
80 |
+
|
81 |
+
// Fire the same event over again
|
82 |
+
$(elem).click();
|
83 |
+
},
|
84 |
+
onFailure: function() {
|
85 |
+
|
86 |
+
// Set the flag to true
|
87 |
+
processedVZero = false;
|
88 |
+
|
89 |
+
stopLoading();
|
90 |
+
|
91 |
+
// We're no longer stopping the events
|
92 |
+
already_placing_order = false;
|
93 |
+
|
94 |
+
}
|
95 |
+
});
|
96 |
+
});
|
97 |
+
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
}
|
102 |
+
|
103 |
+
});
|
104 |
+
});
|
105 |
+
|
106 |
+
// It's not been ran so set it to false
|
107 |
+
var PayPalCompleteRan = false;
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Wrap the functionality needed to start loading
|
111 |
+
**/
|
112 |
+
startLoading = function(noMessage) {
|
113 |
+
|
114 |
+
var submitElement = $('onestepcheckout-place-order');
|
115 |
+
|
116 |
+
/* Disable button to avoid multiple clicks */
|
117 |
+
submitElement.removeClassName('orange').addClassName('grey');
|
118 |
+
submitElement.disabled = true;
|
119 |
+
|
120 |
+
// Add in our loader event
|
121 |
+
var loaderElement = new Element('span').
|
122 |
+
addClassName('onestepcheckout-place-order-loading');
|
123 |
+
|
124 |
+
if(noMessage != true) {
|
125 |
+
loaderElement.update('<?php echo $this->__('Please wait, processing your order...'); ?>');
|
126 |
+
}
|
127 |
+
|
128 |
+
// Append it into the correct area
|
129 |
+
submitElement.parentNode.appendChild(loaderElement);
|
130 |
+
|
131 |
+
};
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Wrap the functionality to stop things loading
|
135 |
+
**/
|
136 |
+
stopLoading = function() {
|
137 |
+
|
138 |
+
// Grab the submit button
|
139 |
+
submitElement = $('onestepcheckout-place-order');
|
140 |
+
|
141 |
+
// Remove the loading stuff on the form
|
142 |
+
submitElement.addClassName('orange').removeClassName('grey');
|
143 |
+
submitElement.removeAttribute('disabled');
|
144 |
+
|
145 |
+
// Remove the loader element
|
146 |
+
if(submitElement.next('.onestepcheckout-place-order-loading') != undefined) {
|
147 |
+
submitElement.next('.onestepcheckout-place-order-loading').remove();
|
148 |
+
}
|
149 |
+
|
150 |
+
};
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Function to run once PayPal has been completed
|
154 |
+
*/
|
155 |
+
completePayPal = function(obj) {
|
156 |
+
|
157 |
+
// Check the flag to make sure we're good to run the function
|
158 |
+
if(!PayPalCompleteRan) {
|
159 |
+
|
160 |
+
// Mark the flag as true
|
161 |
+
PayPalCompleteRan = true;
|
162 |
+
|
163 |
+
// Force check
|
164 |
+
payment.switchMethod('gene_braintree_paypal');
|
165 |
+
|
166 |
+
// Re-enable the form
|
167 |
+
$('paypal-payment-nonce').removeAttribute('disabled');
|
168 |
+
$('paypal-payment-nonce').value = obj.nonce;
|
169 |
+
|
170 |
+
// We have to disable the credit card one
|
171 |
+
$('creditcard-payment-nonce').setAttribute('disabled', 'disabled');
|
172 |
+
|
173 |
+
// Hide the button
|
174 |
+
hidePayPalButton();
|
175 |
+
|
176 |
+
// Submit the checkout
|
177 |
+
$$('.onestepcheckout-place-order').first().click();
|
178 |
+
|
179 |
+
}
|
180 |
+
|
181 |
+
};
|
182 |
+
|
183 |
+
// Flag to check if the PayPal button is already loading
|
184 |
+
var PayPalButtonLoading = false;
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Easily add the PayPal button into the DOM
|
188 |
+
*/
|
189 |
+
addPayPalButton = function() {
|
190 |
+
|
191 |
+
// Check we can locate the submit button
|
192 |
+
if($('onestepcheckout-place-order') != undefined && $('paypal-complete') == undefined && PayPalButtonLoading == false) {
|
193 |
+
|
194 |
+
// The button is loading
|
195 |
+
PayPalButtonLoading = true;
|
196 |
+
|
197 |
+
// Start the loading process
|
198 |
+
startLoading(true);
|
199 |
+
|
200 |
+
// Update the data contained within the classes
|
201 |
+
vzero.updateData(function () {
|
202 |
+
|
203 |
+
// Cancel said loading process
|
204 |
+
stopLoading();
|
205 |
+
|
206 |
+
// The button is no longer loading
|
207 |
+
PayPalButtonLoading = false;
|
208 |
+
|
209 |
+
// Validate the payment method is still correct
|
210 |
+
if(payment.currentMethod == 'gene_braintree_paypal' && $('paypal-complete') == undefined) {
|
211 |
+
|
212 |
+
// Set the flag to false as we've created a new button
|
213 |
+
PayPalCompleteRan = false;
|
214 |
+
|
215 |
+
// Hide the submit button
|
216 |
+
$('onestepcheckout-place-order').hide();
|
217 |
+
|
218 |
+
// Add in our PayPal button
|
219 |
+
$('onestepcheckout-place-order').up().insert('<div id="paypal-complete"><div id="paypal-container"></div><label id="paypal-label"><?php echo $this->__('Complete checkout with'); ?> </label></div>');
|
220 |
+
|
221 |
+
// Always stop the window from opening
|
222 |
+
$('paypal-complete').observe('click', function(event) {
|
223 |
+
|
224 |
+
// First validate the form
|
225 |
+
var form = new VarienForm('onestepcheckout-form');
|
226 |
+
|
227 |
+
// Validate the form like the parent method
|
228 |
+
if(!form.validator.validate()) {
|
229 |
+
|
230 |
+
// Sadly we're unable to intercept the PayPal window in any other way then just hard closing it
|
231 |
+
vzeroPaypal.closePayPalWindow();
|
232 |
+
}
|
233 |
+
});
|
234 |
+
|
235 |
+
// Add in the PayPal button
|
236 |
+
vzeroPaypal.addPayPalButton({
|
237 |
+
onSuccess: completePayPal
|
238 |
+
});
|
239 |
+
}
|
240 |
+
|
241 |
+
});
|
242 |
+
|
243 |
+
} else if($('paypal-complete') != undefined && PayPalButtonLoading == false) {
|
244 |
+
|
245 |
+
// The button is loading
|
246 |
+
PayPalButtonLoading = true;
|
247 |
+
|
248 |
+
// Start the loading process
|
249 |
+
startLoading(true);
|
250 |
+
|
251 |
+
// Update the data contained within the classes
|
252 |
+
vzero.updateData(function () {
|
253 |
+
|
254 |
+
// The button is no longer loading
|
255 |
+
PayPalButtonLoading = false;
|
256 |
+
|
257 |
+
// Cancel said loading process
|
258 |
+
stopLoading();
|
259 |
+
|
260 |
+
// Validate the payment method is still correct
|
261 |
+
if(payment.currentMethod == 'gene_braintree_paypal') {
|
262 |
+
|
263 |
+
// Set the flag to false as we've created a new button
|
264 |
+
PayPalCompleteRan = false;
|
265 |
+
|
266 |
+
// Hide the submit button
|
267 |
+
$('onestepcheckout-place-order').hide();
|
268 |
+
|
269 |
+
// Add in our PayPal button
|
270 |
+
$('paypal-complete').show();
|
271 |
+
}
|
272 |
+
|
273 |
+
});
|
274 |
+
|
275 |
+
}
|
276 |
+
|
277 |
+
};
|
278 |
+
|
279 |
+
/**
|
280 |
+
* As we need to remove the PayPal button in multiple places
|
281 |
+
*/
|
282 |
+
hidePayPalButton = function() {
|
283 |
+
|
284 |
+
// Just in case things are still loading
|
285 |
+
stopLoading();
|
286 |
+
|
287 |
+
// If the user has selected a different payment method make some modifications
|
288 |
+
if($('onestepcheckout-place-order') != undefined) {
|
289 |
+
$('onestepcheckout-place-order').show();
|
290 |
+
}
|
291 |
+
|
292 |
+
// Remove the PayPal element
|
293 |
+
if($('paypal-complete') != undefined) {
|
294 |
+
$('paypal-complete').hide();
|
295 |
+
}
|
296 |
+
|
297 |
+
};
|
298 |
+
|
299 |
+
// Check if the payment method is the default
|
300 |
+
if(payment != undefined) {
|
301 |
+
if((payment.currentMethod == 'gene_braintree_paypal' && $('paypal-saved-accounts') == undefined) || ($$('#paypal-saved-accounts input:checked[type=radio]').first() != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other')) {
|
302 |
+
|
303 |
+
// Verify that vzero is defined before attempting to use it
|
304 |
+
if(typeof vzeroPaypal !== 'undefined') {
|
305 |
+
|
306 |
+
// Set the amount for the PayPal modal window
|
307 |
+
vzeroPaypal.setPricing('<?php echo Mage::getSingleton('checkout/cart')->getQuote()->collectTotals()->getGrandTotal(); ?>', '<?php echo Mage::getSingleton('checkout/cart')->getQuote()->getBaseCurrencyCode(); ?>');
|
308 |
+
}
|
309 |
+
|
310 |
+
addPayPalButton();
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
// Store the original payment method
|
315 |
+
var paymentOriginal = Payment.prototype.switchMethod;
|
316 |
+
|
317 |
+
// Intercept the save function
|
318 |
+
Payment.prototype.switchMethod = function (method) {
|
319 |
+
|
320 |
+
// Detect PayPal choice
|
321 |
+
if(method == 'gene_braintree_paypal') {
|
322 |
+
|
323 |
+
if($('paypal-saved-accounts') == undefined) {
|
324 |
+
addPayPalButton();
|
325 |
+
} else if($('paypal-saved-accounts') != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first() != undefined && $$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other') {
|
326 |
+
addPayPalButton();
|
327 |
+
} else {
|
328 |
+
hidePayPalButton();
|
329 |
+
}
|
330 |
+
|
331 |
+
} else {
|
332 |
+
hidePayPalButton();
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
// Run the original function
|
337 |
+
return paymentOriginal.apply(this, arguments);
|
338 |
+
|
339 |
+
};
|
340 |
+
|
341 |
+
// If we have any saved accounts we'll need to do something jammy
|
342 |
+
if($$('#paypal-saved-accounts input[type=radio]').first() != undefined) {
|
343 |
+
|
344 |
+
// Loop through each radio button
|
345 |
+
$$('#paypal-saved-accounts input[type=radio]').each(function (savedAccount) {
|
346 |
+
|
347 |
+
// Observe them changing
|
348 |
+
Event.observe(savedAccount, 'click', function (ele) {
|
349 |
+
if(savedAccount.value == 'other') {
|
350 |
+
addPayPalButton();
|
351 |
+
} else {
|
352 |
+
hidePayPalButton();
|
353 |
+
}
|
354 |
+
});
|
355 |
+
});
|
356 |
+
}
|
357 |
+
|
358 |
+
// What should happen if the user closes the 3D secure window?
|
359 |
+
vzero.close3dSecureMethod(function() {
|
360 |
+
stopLoading();
|
361 |
+
});
|
362 |
+
|
363 |
+
// Observe all Ajax requests for changes
|
364 |
+
vzero.observeAjaxRequests(function() {
|
365 |
+
|
366 |
+
// If the method is PayPal remove and re-add the PayPal button
|
367 |
+
if(payment.currentMethod == 'gene_braintree_paypal') {
|
368 |
+
hidePayPalButton();
|
369 |
+
addPayPalButton();
|
370 |
+
} else {
|
371 |
+
vzero.updateData();
|
372 |
+
}
|
373 |
+
|
374 |
+
});
|
375 |
+
|
376 |
+
</script>
|
377 |
+
|
378 |
+
<!-- Fix some minor styling issues with our nested form-list -->
|
379 |
+
<style type="text/css">
|
380 |
+
#credit-card-form .form-list {
|
381 |
+
margin: 10px 0 0 0!important;
|
382 |
+
padding: 0!important;
|
383 |
+
border: 0!important;
|
384 |
+
}
|
385 |
+
#credit-card-form .form-list:before, #credit-card-form .form-list:after {
|
386 |
+
border: 0!important;
|
387 |
+
}
|
388 |
+
|
389 |
+
#paypal-container {
|
390 |
+
float: right;
|
391 |
+
}
|
392 |
+
#paypal-label {
|
393 |
+
line-height: 44px;
|
394 |
+
float: right;
|
395 |
+
margin-right: 12px;
|
396 |
+
}
|
397 |
+
#braintree-paypal-button {
|
398 |
+
padding: 0!important;
|
399 |
+
line-height: unset!important;
|
400 |
+
float: left!important;
|
401 |
+
}
|
402 |
+
</style>
|
app/design/frontend/base/default/template/gene/braintree/js/setup.phtml
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Setup the JavaScript classes with their required fields
|
4 |
+
*/
|
5 |
+
/* @var $this Gene_Braintree_Block_Js */
|
6 |
+
?>
|
7 |
+
<script type="text/javascript">
|
8 |
+
|
9 |
+
// Pass some data over to vZero integration JS
|
10 |
+
var vzero = new vZero(
|
11 |
+
'gene_braintree_creditcard',
|
12 |
+
'<?php echo $this->getClientToken(); ?>',
|
13 |
+
<?php echo $this->is3DEnabled(); ?>,
|
14 |
+
false,
|
15 |
+
false,
|
16 |
+
'<?php echo Mage::getUrl('braintree/checkout/quoteTotal', array('_secure' => Mage::app()->getFrontController()->getRequest()->isSecure())); ?>',
|
17 |
+
'<?php echo Mage::getUrl('braintree/checkout/tokenizeCard', array('_secure' => Mage::app()->getFrontController()->getRequest()->isSecure())); ?>'
|
18 |
+
);
|
19 |
+
|
20 |
+
<?php if($this->isPayPalActive()): ?>
|
21 |
+
|
22 |
+
// Pass some data through to the PayPal integration
|
23 |
+
var vzeroPaypal = new vZeroPayPalButton(
|
24 |
+
'<?php echo $this->getClientToken(); ?>',
|
25 |
+
'<?php echo Mage::app()->getStore()->getFrontendName(); ?>',
|
26 |
+
<?php echo $this->getSingleUse(); ?>,
|
27 |
+
'<?php echo $this->getLocale(); ?>',
|
28 |
+
<?php echo $this->getSingleFutureUse(); ?>
|
29 |
+
);
|
30 |
+
|
31 |
+
<?php endif; ?>
|
32 |
+
|
33 |
+
// Init the environment
|
34 |
+
vzero.init();
|
35 |
+
|
36 |
+
</script>
|
app/design/frontend/base/default/template/gene/braintree/paypal.phtml
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/* @var $this Gene_Braintree_Block_Paypal */
|
3 |
+
?>
|
4 |
+
<div class="form-list" id="payment_form_<?php echo $this->getMethodCode() ?>" style="display: none;">
|
5 |
+
|
6 |
+
<?php if($this->hasSavedDetails() && $this->getMethod()->isVaultEnabled()): ?>
|
7 |
+
|
8 |
+
<label><?php echo $this->__('Linked Accounts'); ?></label>
|
9 |
+
<p><?php echo $this->__('The following PayPal accounts are currently linked with your account.'); ?></p>
|
10 |
+
<table width="100%" cellspacing="0" cellpadding="0" id="paypal-saved-accounts">
|
11 |
+
<?php
|
12 |
+
$count = 0;
|
13 |
+
foreach($this->getSavedDetails() as $savedDetail):
|
14 |
+
?>
|
15 |
+
<tr>
|
16 |
+
<td width="20"><input type="radio" name="payment[paypal_payment_method_token]" id="<?php echo $savedDetail->token; ?>" value="<?php echo $savedDetail->token; ?>"<?php echo ($count == 0 ? ' checked="checked"' : ''); ?>/></td>
|
17 |
+
<td valign="middle"><label for="<?php echo $savedDetail->token; ?>" style="line-height: 48px;"><img src="<?php echo $this->getSkinUrl('images/gene/braintree/PP.png') ?>" align="left" /> <?php echo $savedDetail->email; ?></label></td>
|
18 |
+
</tr>
|
19 |
+
<?php
|
20 |
+
++$count;
|
21 |
+
endforeach; ?>
|
22 |
+
<tr>
|
23 |
+
<td width="20"><input type="radio" name="payment[paypal_payment_method_token]" id="other-paypal" value="other" /></td>
|
24 |
+
<td><label for="other-paypal"><?php echo $this->__('New PayPal Account'); ?></label></td>
|
25 |
+
</tr>
|
26 |
+
</table>
|
27 |
+
|
28 |
+
<?php endif; ?>
|
29 |
+
|
30 |
+
<div class="paypal-info"<?php echo ($this->hasSavedDetails() && $this->getMethod()->isVaultEnabled() ? ' style="display: none;"' : ''); ?>>
|
31 |
+
<p><?php echo $this->__('You will complete your payment via PayPal after the order review step.'); ?></p>
|
32 |
+
|
33 |
+
<?php if($this->canSavePayPal()): ?>
|
34 |
+
<input type="checkbox" title="<?php echo $this->__('Save this account for future use') ?>"
|
35 |
+
class="input-checkbox" id="gene_braintree_paypal_store_in_vault" name="payment[save_paypal]"
|
36 |
+
value="1"/>
|
37 |
+
<label for="gene_braintree_paypal_store_in_vault" style="float:none;"><?php echo $this->__(
|
38 |
+
'Save this account for future use'
|
39 |
+
) ?></label>
|
40 |
+
<?php endif; ?>
|
41 |
+
|
42 |
+
<?php /* Our hidden field to store the payment nonce */ ?>
|
43 |
+
<input type="hidden" name="payment[payment_method_nonce]" id="paypal-payment-nonce" />
|
44 |
+
</div>
|
45 |
+
|
46 |
+
</div>
|
47 |
+
|
48 |
+
<!-- Attach an event onto all radio buttons -->
|
49 |
+
<script type="text/javascript">
|
50 |
+
|
51 |
+
// Set a flag to determine whether the PayPal flag is initialized
|
52 |
+
var PayPalInit = false;
|
53 |
+
|
54 |
+
// Wrap our logic in a function so we can init in different ways
|
55 |
+
initPayPal = function() {
|
56 |
+
|
57 |
+
// Verify that vzero is defined before attempting to use it
|
58 |
+
if (typeof vzeroPaypal !== 'undefined') {
|
59 |
+
|
60 |
+
// Yay we're good to go
|
61 |
+
PayPalInit = true;
|
62 |
+
|
63 |
+
// Always set the amount as it's needed within 3D secure requests
|
64 |
+
vzeroPaypal.setPricing('<?php echo Mage::getSingleton('checkout/cart')->getQuote()->collectTotals()->getGrandTotal(); ?>', '<?php echo Mage::getSingleton('checkout/cart')->getQuote()->getQuoteCurrencyCode(); ?>');
|
65 |
+
}
|
66 |
+
|
67 |
+
$$('#paypal-saved-accounts input[type="radio"]').each(function(elm) {
|
68 |
+
Element.observe(elm, 'change', function(event) {
|
69 |
+
|
70 |
+
// Has the user selected other?
|
71 |
+
if($$('#paypal-saved-accounts input:checked[type=radio]').first().value == 'other') {
|
72 |
+
|
73 |
+
// Show the form
|
74 |
+
$$('.paypal-info').first().show();
|
75 |
+
|
76 |
+
// Enable the form
|
77 |
+
$$('.paypal-info input, .paypal-info select').each(function(formElement) {
|
78 |
+
formElement.removeAttribute('disabled');
|
79 |
+
});
|
80 |
+
|
81 |
+
} else {
|
82 |
+
|
83 |
+
// Hide the form
|
84 |
+
$$('.paypal-info').first().hide();
|
85 |
+
|
86 |
+
// Disable any form elements within the form
|
87 |
+
$$('.paypal-info input, .paypal-info select').each(function(formElement) {
|
88 |
+
formElement.setAttribute('disabled', 'disabled');
|
89 |
+
});
|
90 |
+
}
|
91 |
+
});
|
92 |
+
});
|
93 |
+
|
94 |
+
};
|
95 |
+
|
96 |
+
// Init PayPal on load
|
97 |
+
initPayPal();
|
98 |
+
|
99 |
+
// If the function didn't run on the load of the payment method do it on dom:loaded
|
100 |
+
if(!PayPalInit) {
|
101 |
+
document.observe('dom:loaded', function () {
|
102 |
+
initPayPal();
|
103 |
+
});
|
104 |
+
}
|
105 |
+
|
106 |
+
</script>
|
app/design/frontend/base/default/template/gene/braintree/paypal/info.phtml
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<p><strong><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></strong></p>
|
2 |
+
|
3 |
+
<?php if ($_specificInfo = $this->getSpecificInformation()):?>
|
4 |
+
<table>
|
5 |
+
<tbody>
|
6 |
+
<?php foreach ($_specificInfo as $_label => $_value):
|
7 |
+
if($_value):
|
8 |
+
?>
|
9 |
+
<tr>
|
10 |
+
<th style="text-align: left;font-weight:bold;padding: 3px 0;"><?php echo $this->escapeHtml($_label)?>:</th>
|
11 |
+
</tr>
|
12 |
+
<tr>
|
13 |
+
<td style="padding: 3px 0;"><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n"))?></td>
|
14 |
+
</tr>
|
15 |
+
<?php endif;
|
16 |
+
endforeach; ?>
|
17 |
+
</tbody>
|
18 |
+
</table>
|
19 |
+
<?php endif;?>
|
20 |
+
|
21 |
+
<?php echo $this->getChildHtml()?>
|
app/etc/modules/Gene_Braintree.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Gene_Braintree>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Gene_Braintree>
|
8 |
+
</modules>
|
9 |
+
</config>
|
app/locale/en_US/Gene_Braintree.csv
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"Braintree v.zero - Configuration","Braintree v.zero - Configuration"
|
2 |
+
"4px 0 8px 0;" border="0"/><br />To use this module you will need an existing production or sandbox Braintree account. You can apply at <a href="https://www.braintreepayments.com">braintreepayments.com</a>.<br />Braintree v.zero integration provided by <a href="http://gene.co.uk/" target="_blank">Gene Commerce</a>.","4px 0 8px 0;" border="0"/><br />To use this module you will need an existing production or sandbox Braintree account. You can apply at <a href="https://www.braintreepayments.com">braintreepayments.com</a>.<br />Braintree v.zero integration provided by <a href="http://gene.co.uk/" target="_blank">Gene Commerce</a>."
|
3 |
+
"Braintree PHP SDK Version","Braintree PHP SDK Version"
|
4 |
+
"Magento Braintree v.zero Version","Magento Braintree v.zero Version"
|
5 |
+
"Braintree Account Details","Braintree Account Details"
|
6 |
+
"Environment","Environment"
|
7 |
+
"<strong>Warning:</strong> Do not use 'Sandbox' on a production environment.<br />","<strong>Warning:</strong> Do not use 'Sandbox' on a production environment.<br />"
|
8 |
+
"Your API details above will need to reflect your Sandbox or your Production account.","Your API details above will need to reflect your Sandbox or your Production account."
|
9 |
+
"Sandbox","Sandbox"
|
10 |
+
"Production","Production"
|
11 |
+
"Merchant ID","Merchant ID"
|
12 |
+
"Merchant Account ID","Merchant Account ID"
|
13 |
+
"Public Key","Public Key"
|
14 |
+
"Private Key","Private Key"
|
15 |
+
"Testing Settings","Testing Settings"
|
16 |
+
"Debug","Debug"
|
17 |
+
"Debugging will cause a log to be written to the <strong>var/log/gene_braintree.log</strong> file. As no credit card data ever hits the server this file will never contain any crucial customer information.","Debugging will cause a log to be written to the <strong>var/log/gene_braintree.log</strong> file. As no credit card data ever hits the server this file will never contain any crucial customer information."
|
18 |
+
"Braintree v.zero - PayPal","Braintree v.zero - PayPal"
|
19 |
+
"6px 0;" /><br />You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details.","6px 0;" /><br />You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details."
|
20 |
+
"Enabled","Enabled"
|
21 |
+
"Title","Title"
|
22 |
+
"Capture","Capture"
|
23 |
+
"Complete Order Status","Complete Order Status"
|
24 |
+
"Features","Features"
|
25 |
+
"Payment Type","Payment Type"
|
26 |
+
"<strong>Single Payment</strong> - Will only require the customer to sign in, we will only be able to take a single payment<br />","<strong>Single Payment</strong> - Will only require the customer to sign in, we will only be able to take a single payment<br />"
|
27 |
+
"<strong>Future Payments</strong> - Allows us to save the customers PayPal account for later purchases and use with the Vault","<strong>Future Payments</strong> - Allows us to save the customers PayPal account for later purchases and use with the Vault"
|
28 |
+
"Single Payment","Single Payment"
|
29 |
+
"Future Payments","Future Payments"
|
30 |
+
"Enable Vault","Enable Vault"
|
31 |
+
"Storing the customers PayPal in the vault will allow them to instantly purchase any product without having to login to PayPal again.","Storing the customers PayPal in the vault will allow them to instantly purchase any product without having to login to PayPal again."
|
32 |
+
"Locale","Locale"
|
33 |
+
"The locale for the PayPal popup window","The locale for the PayPal popup window"
|
34 |
+
"Australia","Australia"
|
35 |
+
"Canada","Canada"
|
36 |
+
"France","France"
|
37 |
+
"Germany","Germany"
|
38 |
+
"Great Britain & Ireland","Great Britain & Ireland"
|
39 |
+
"Hong Kong","Hong Kong"
|
40 |
+
"Italy","Italy"
|
41 |
+
"Spain","Spain"
|
42 |
+
"United States","United States"
|
43 |
+
"Display","Display"
|
44 |
+
"Sort Order","Sort Order"
|
45 |
+
"Braintree v.zero - Credit Card","Braintree v.zero - Credit Card"
|
46 |
+
"You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details.","You must first configure the <strong>Braintree v.zero - Configuration</strong> section with your Braintree account details."
|
47 |
+
"Payment Action","Payment Action"
|
48 |
+
"<strong>Authorize</strong> - Will only auth the payment and store a token, the transaction will not be settled.<br />","<strong>Authorize</strong> - Will only auth the payment and store a token, the transaction will not be settled.<br />"
|
49 |
+
"<strong>Authorize & Capture</strong> - We will instantly settle the transaction within the checkout.","<strong>Authorize & Capture</strong> - We will instantly settle the transaction within the checkout."
|
50 |
+
"Authorize","Authorize"
|
51 |
+
"Authorize & Capture","Authorize & Capture"
|
52 |
+
"Capture Action","Capture Action"
|
53 |
+
"If you're just authorizing transactions you can define at what point they should be submitted for settlement.","If you're just authorizing transactions you can define at what point they should be submitted for settlement."
|
54 |
+
"Invoice","Invoice"
|
55 |
+
"Shipment","Shipment"
|
56 |
+
"New Order Status","New Order Status"
|
57 |
+
"Enable Vault/Saved Cards","Enable Vault/Saved Cards"
|
58 |
+
"The vault allows you to securely store the customers credit card on Braintree's servers. We're provided with a token which allows the customer to make future payments without having to enter any details again.","The vault allows you to securely store the customers credit card on Braintree's servers. We're provided with a token which allows the customer to make future payments without having to enter any details again."
|
59 |
+
"Enable 3D Secure","Enable 3D Secure"
|
60 |
+
"The 3D Secure feature enables the shopper to enter a password to confirm their identity with the card issuer. If accepted they then complete their order, and when received by you, you have much more confidence that is genuine and real.","The 3D Secure feature enables the shopper to enter a password to confirm their identity with the card issuer. If accepted they then complete their order, and when received by you, you have much more confidence that is genuine and real."
|
61 |
+
"CVV Verification","CVV Verification"
|
62 |
+
"Should we verify the CVV against the card?","Should we verify the CVV against the card?"
|
63 |
+
"Kount Merchant ID","Kount Merchant ID"
|
64 |
+
"Braintree offers a direct integration with Kount, our partner for providing advanced fraud detection technology. To use this feature, you must be processing at least 2500 transactions per month, and you’ll be subject to additional fees from Kount for their services. To get started, contact accounts@braintreepayments.com. You can view more information <a href="https://developers.braintreepayments.com/javascript+php/guides/fraud-tools">here</a>.","Braintree offers a direct integration with Kount, our partner for providing advanced fraud detection technology. To use this feature, you must be processing at least 2500 transactions per month, and you’ll be subject to additional fees from Kount for their services. To get started, contact accounts@braintreepayments.com. You can view more information <a href="https://developers.braintreepayments.com/javascript+php/guides/fraud-tools">here</a>."
|
65 |
+
"Credit Card Types","Credit Card Types"
|
66 |
+
"Payment from Applicable Countries","Payment from Applicable Countries"
|
67 |
+
"Payment from Specific Countries","Payment from Specific Countries"
|
68 |
+
"Braintree Transactions","Braintree Transactions"
|
69 |
+
"Valid Credentials","Valid Credentials"
|
70 |
+
"You're ready to accept payments via Braintree","You're ready to accept payments via Braintree"
|
71 |
+
"Authorization Expired","Authorization Expired"
|
72 |
+
"Authorizing","Authorizing"
|
73 |
+
"Authorized","Authorized"
|
74 |
+
"Gateway Rejected","Gateway Rejected"
|
75 |
+
"Failed","Failed"
|
76 |
+
"Processor Declined","Processor Declined"
|
77 |
+
"Settled","Settled"
|
78 |
+
"Settling","Settling"
|
79 |
+
"Submitted For Settlement","Submitted For Settlement"
|
80 |
+
"Voided","Voided"
|
81 |
+
"Unrecognized","Unrecognized"
|
82 |
+
"Settlement Declined","Settlement Declined"
|
83 |
+
"Settlement Pending","Settlement Pending"
|
84 |
+
"ID","ID"
|
85 |
+
"Transaction Date","Transaction Date"
|
86 |
+
"Magento Order ID","Magento Order ID"
|
87 |
+
"Magento Status","Magento Status"
|
88 |
+
"Type","Type"
|
89 |
+
"Payment Information","Payment Information"
|
90 |
+
"Amount","Amount"
|
91 |
+
"Currency","Currency"
|
92 |
+
"Braintree Status","Braintree Status"
|
93 |
+
"CSV","CSV"
|
94 |
+
"Excel XML","Excel XML"
|
95 |
+
"Your card payment has failed, please try again.","Your card payment has failed, please try again."
|
96 |
+
"We require a CVV when creating card transactions.","We require a CVV when creating card transactions."
|
97 |
+
"There was an issue whilst trying to process your card payment, please try again or another method.","There was an issue whilst trying to process your card payment, please try again or another method."
|
98 |
+
"Your transaction has been declined, please try another payment method or contacting your issuing bank.","Your transaction has been declined, please try another payment method or contacting your issuing bank."
|
99 |
+
"%s. Please try again or attempt refreshing the page.","%s. Please try again or attempt refreshing the page."
|
100 |
+
"Your 3D secure verification has failed, please try using another card, or payment method.","Your 3D secure verification has failed, please try using another card, or payment method."
|
101 |
+
"There has been an issue processing your PayPal payment, please try again.","There has been an issue processing your PayPal payment, please try again."
|
102 |
+
"We were unable to complete your purchase through PayPal, please try again or an alternative payment method.","We were unable to complete your purchase through PayPal, please try again or an alternative payment method."
|
103 |
+
"The following PayPal accounts are currently linked with your account.","The following PayPal accounts are currently linked with your account."
|
104 |
+
"The following credit cards accounts are currently linked with your account.","The following credit cards accounts are currently linked with your account."
|
105 |
+
"You will complete your payment via PayPal after the order review step.","You will complete your payment via PayPal after the order review step."
|
106 |
+
"You're able to use any of the listed payment methods below when purchasing through our checkout, you're able to add new payment methods within the checkout.","You're able to use any of the listed payment methods below when purchasing through our checkout, you're able to add new payment methods within the checkout."
|
107 |
+
"You currently have no saved payment information, you can save a payment method when making a purchase.","You currently have no saved payment information, you can save a payment method when making a purchase."
|
108 |
+
"Saved Payment Information","Saved Payment Information"
|
109 |
+
"Save this account for future use","Save this account for future use"
|
110 |
+
"Complete checkout with","Complete checkout with"
|
111 |
+
"Are you sure you want to remove this payment method?","Are you sure you want to remove this payment method?"
|
112 |
+
"Saved Cards","Saved Cards"
|
113 |
+
"Expires:","Expires:"
|
114 |
+
"New Credit Card","New Credit Card"
|
115 |
+
"Credit Card Number","Credit Card Number"
|
116 |
+
"Expiration Date","Expiration Date"
|
117 |
+
"Card Verification Number","Card Verification Number"
|
118 |
+
"Save this card for future use","Save this card for future use"
|
119 |
+
"Sadly, we're unable to accept this type of card, please try another.","Sadly, we're unable to accept this type of card, please try another."
|
120 |
+
"We cannot detect the card type for this card number, please try re-entering your card details.","We cannot detect the card type for this card number, please try re-entering your card details."
|
121 |
+
"We cannot match this card number to any of our accepted payment methods, please try re-entering your details.","We cannot match this card number to any of our accepted payment methods, please try re-entering your details."
|
js/gene/braintree/braintree.js
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
!function(){function t(e,n){e instanceof t?(this.enc=e.enc,this.pos=e.pos):(this.enc=e,this.pos=n)}function e(t,e,n,i,r){this.stream=t,this.header=e,this.length=n,this.tag=i,this.sub=r}function n(t){var e,n,i="";for(e=0;e+3<=t.length;e+=3)n=parseInt(t.substring(e,e+3),16),i+=ee.charAt(n>>6)+ee.charAt(63&n);for(e+1==t.length?(n=parseInt(t.substring(e,e+1),16),i+=ee.charAt(n<<2)):e+2==t.length&&(n=parseInt(t.substring(e,e+2),16),i+=ee.charAt(n>>2)+ee.charAt((3&n)<<4));(3&i.length)>0;)i+=ne;return i}function i(t){var e,n,i,r="",o=0;for(e=0;e<t.length&&t.charAt(e)!=ne;++e)i=ee.indexOf(t.charAt(e)),0>i||(0==o?(r+=l(i>>2),n=3&i,o=1):1==o?(r+=l(n<<2|i>>4),n=15&i,o=2):2==o?(r+=l(n),r+=l(i>>2),n=3&i,o=3):(r+=l(n<<2|i>>4),r+=l(15&i),o=0));return 1==o&&(r+=l(n<<2)),r}function r(t){var e,n=i(t),r=new Array;for(e=0;2*e<n.length;++e)r[e]=parseInt(n.substring(2*e,2*e+2),16);return r}function o(t,e,n){null!=t&&("number"==typeof t?this.fromNumber(t,e,n):null==e&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,e))}function s(){return new o(null)}function a(t,e,n,i,r,o){for(;--o>=0;){var s=e*this[t++]+n[i]+r;r=Math.floor(s/67108864),n[i++]=67108863&s}return r}function u(t,e,n,i,r,o){for(var s=32767&e,a=e>>15;--o>=0;){var u=32767&this[t],c=this[t++]>>15,l=a*u+c*s;u=s*u+((32767&l)<<15)+n[i]+(1073741823&r),r=(u>>>30)+(l>>>15)+a*c+(r>>>30),n[i++]=1073741823&u}return r}function c(t,e,n,i,r,o){for(var s=16383&e,a=e>>14;--o>=0;){var u=16383&this[t],c=this[t++]>>14,l=a*u+c*s;u=s*u+((16383&l)<<14)+n[i]+r,r=(u>>28)+(l>>14)+a*c,n[i++]=268435455&u}return r}function l(t){return ue.charAt(t)}function p(t,e){var n=ce[t.charCodeAt(e)];return null==n?-1:n}function h(t){for(var e=this.t-1;e>=0;--e)t[e]=this[e];t.t=this.t,t.s=this.s}function d(t){this.t=1,this.s=0>t?-1:0,t>0?this[0]=t:-1>t?this[0]=t+this.DV:this.t=0}function f(t){var e=s();return e.fromInt(t),e}function m(t,e){var n;if(16==e)n=4;else if(8==e)n=3;else if(256==e)n=8;else if(2==e)n=1;else if(32==e)n=5;else{if(4!=e)return void this.fromRadix(t,e);n=2}this.t=0,this.s=0;for(var i=t.length,r=!1,s=0;--i>=0;){var a=8==n?255&t[i]:p(t,i);0>a?"-"==t.charAt(i)&&(r=!0):(r=!1,0==s?this[this.t++]=a:s+n>this.DB?(this[this.t-1]|=(a&(1<<this.DB-s)-1)<<s,this[this.t++]=a>>this.DB-s):this[this.t-1]|=a<<s,s+=n,s>=this.DB&&(s-=this.DB))}8==n&&0!=(128&t[0])&&(this.s=-1,s>0&&(this[this.t-1]|=(1<<this.DB-s)-1<<s)),this.clamp(),r&&o.ZERO.subTo(this,this)}function y(){for(var t=this.s&this.DM;this.t>0&&this[this.t-1]==t;)--this.t}function g(t){if(this.s<0)return"-"+this.negate().toString(t);var e;if(16==t)e=4;else if(8==t)e=3;else if(2==t)e=1;else if(32==t)e=5;else{if(4!=t)return this.toRadix(t);e=2}var n,i=(1<<e)-1,r=!1,o="",s=this.t,a=this.DB-s*this.DB%e;if(s-->0)for(a<this.DB&&(n=this[s]>>a)>0&&(r=!0,o=l(n));s>=0;)e>a?(n=(this[s]&(1<<a)-1)<<e-a,n|=this[--s]>>(a+=this.DB-e)):(n=this[s]>>(a-=e)&i,0>=a&&(a+=this.DB,--s)),n>0&&(r=!0),r&&(o+=l(n));return r?o:"0"}function b(){var t=s();return o.ZERO.subTo(this,t),t}function v(){return this.s<0?this.negate():this}function _(t){var e=this.s-t.s;if(0!=e)return e;var n=this.t;if(e=n-t.t,0!=e)return this.s<0?-e:e;for(;--n>=0;)if(0!=(e=this[n]-t[n]))return e;return 0}function w(t){var e,n=1;return 0!=(e=t>>>16)&&(t=e,n+=16),0!=(e=t>>8)&&(t=e,n+=8),0!=(e=t>>4)&&(t=e,n+=4),0!=(e=t>>2)&&(t=e,n+=2),0!=(e=t>>1)&&(t=e,n+=1),n}function E(){return this.t<=0?0:this.DB*(this.t-1)+w(this[this.t-1]^this.s&this.DM)}function S(t,e){var n;for(n=this.t-1;n>=0;--n)e[n+t]=this[n];for(n=t-1;n>=0;--n)e[n]=0;e.t=this.t+t,e.s=this.s}function C(t,e){for(var n=t;n<this.t;++n)e[n-t]=this[n];e.t=Math.max(this.t-t,0),e.s=this.s}function A(t,e){var n,i=t%this.DB,r=this.DB-i,o=(1<<r)-1,s=Math.floor(t/this.DB),a=this.s<<i&this.DM;for(n=this.t-1;n>=0;--n)e[n+s+1]=this[n]>>r|a,a=(this[n]&o)<<i;for(n=s-1;n>=0;--n)e[n]=0;e[s]=a,e.t=this.t+s+1,e.s=this.s,e.clamp()}function x(t,e){e.s=this.s;var n=Math.floor(t/this.DB);if(n>=this.t)return void(e.t=0);var i=t%this.DB,r=this.DB-i,o=(1<<i)-1;e[0]=this[n]>>i;for(var s=n+1;s<this.t;++s)e[s-n-1]|=(this[s]&o)<<r,e[s-n]=this[s]>>i;i>0&&(e[this.t-n-1]|=(this.s&o)<<r),e.t=this.t-n,e.clamp()}function T(t,e){for(var n=0,i=0,r=Math.min(t.t,this.t);r>n;)i+=this[n]-t[n],e[n++]=i&this.DM,i>>=this.DB;if(t.t<this.t){for(i-=t.s;n<this.t;)i+=this[n],e[n++]=i&this.DM,i>>=this.DB;i+=this.s}else{for(i+=this.s;n<t.t;)i-=t[n],e[n++]=i&this.DM,i>>=this.DB;i-=t.s}e.s=0>i?-1:0,-1>i?e[n++]=this.DV+i:i>0&&(e[n++]=i),e.t=n,e.clamp()}function k(t,e){var n=this.abs(),i=t.abs(),r=n.t;for(e.t=r+i.t;--r>=0;)e[r]=0;for(r=0;r<i.t;++r)e[r+n.t]=n.am(0,i[r],e,r,0,n.t);e.s=0,e.clamp(),this.s!=t.s&&o.ZERO.subTo(e,e)}function P(t){for(var e=this.abs(),n=t.t=2*e.t;--n>=0;)t[n]=0;for(n=0;n<e.t-1;++n){var i=e.am(n,e[n],t,2*n,0,1);(t[n+e.t]+=e.am(n+1,2*e[n],t,2*n+1,i,e.t-n-1))>=e.DV&&(t[n+e.t]-=e.DV,t[n+e.t+1]=1)}t.t>0&&(t[t.t-1]+=e.am(n,e[n],t,2*n,0,1)),t.s=0,t.clamp()}function I(t,e,n){var i=t.abs();if(!(i.t<=0)){var r=this.abs();if(r.t<i.t)return null!=e&&e.fromInt(0),void(null!=n&&this.copyTo(n));null==n&&(n=s());var a=s(),u=this.s,c=t.s,l=this.DB-w(i[i.t-1]);l>0?(i.lShiftTo(l,a),r.lShiftTo(l,n)):(i.copyTo(a),r.copyTo(n));var p=a.t,h=a[p-1];if(0!=h){var d=h*(1<<this.F1)+(p>1?a[p-2]>>this.F2:0),f=this.FV/d,m=(1<<this.F1)/d,y=1<<this.F2,g=n.t,b=g-p,v=null==e?s():e;for(a.dlShiftTo(b,v),n.compareTo(v)>=0&&(n[n.t++]=1,n.subTo(v,n)),o.ONE.dlShiftTo(p,v),v.subTo(a,a);a.t<p;)a[a.t++]=0;for(;--b>=0;){var _=n[--g]==h?this.DM:Math.floor(n[g]*f+(n[g-1]+y)*m);if((n[g]+=a.am(0,_,n,b,0,p))<_)for(a.dlShiftTo(b,v),n.subTo(v,n);n[g]<--_;)n.subTo(v,n)}null!=e&&(n.drShiftTo(p,e),u!=c&&o.ZERO.subTo(e,e)),n.t=p,n.clamp(),l>0&&n.rShiftTo(l,n),0>u&&o.ZERO.subTo(n,n)}}}function O(t){var e=s();return this.abs().divRemTo(t,null,e),this.s<0&&e.compareTo(o.ZERO)>0&&t.subTo(e,e),e}function U(t){this.m=t}function R(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function M(t){return t}function N(t){t.divRemTo(this.m,null,t)}function D(t,e,n){t.multiplyTo(e,n),this.reduce(n)}function F(t,e){t.squareTo(e),this.reduce(e)}function L(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var e=3&t;return e=e*(2-(15&t)*e)&15,e=e*(2-(255&t)*e)&255,e=e*(2-((65535&t)*e&65535))&65535,e=e*(2-t*e%this.DV)%this.DV,e>0?this.DV-e:-e}function B(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<<t.DB-15)-1,this.mt2=2*t.t}function j(t){var e=s();return t.abs().dlShiftTo(this.m.t,e),e.divRemTo(this.m,null,e),t.s<0&&e.compareTo(o.ZERO)>0&&this.m.subTo(e,e),e}function z(t){var e=s();return t.copyTo(e),this.reduce(e),e}function V(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var e=0;e<this.m.t;++e){var n=32767&t[e],i=n*this.mpl+((n*this.mph+(t[e]>>15)*this.mpl&this.um)<<15)&t.DM;for(n=e+this.m.t,t[n]+=this.m.am(0,i,t,e,0,this.m.t);t[n]>=t.DV;)t[n]-=t.DV,t[++n]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function H(t,e){t.squareTo(e),this.reduce(e)}function W(t,e,n){t.multiplyTo(e,n),this.reduce(n)}function q(){return 0==(this.t>0?1&this[0]:this.s)}function Q(t,e){if(t>4294967295||1>t)return o.ONE;var n=s(),i=s(),r=e.convert(this),a=w(t)-1;for(r.copyTo(n);--a>=0;)if(e.sqrTo(n,i),(t&1<<a)>0)e.mulTo(i,r,n);else{var u=n;n=i,i=u}return e.revert(n)}function G(t,e){var n;return n=256>t||e.isEven()?new U(e):new B(e),this.exp(t,n)}function Y(t,e){return new o(t,e)}function J(t,e){if(e<t.length+11)throw new Error("Message too long for RSA");for(var n=new Array,i=t.length-1;i>=0&&e>0;){var r=t.charCodeAt(i--);128>r?n[--e]=r:r>127&&2048>r?(n[--e]=63&r|128,n[--e]=r>>6|192):(n[--e]=63&r|128,n[--e]=r>>6&63|128,n[--e]=r>>12|224)}n[--e]=0;for(var s=0,a=0,u=0;e>2;)0==u&&(a=le.random.randomWords(1,0)[0]),s=a>>u&255,u=(u+8)%32,0!=s&&(n[--e]=s);return n[--e]=2,n[--e]=0,new o(n)}function Z(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function K(t,e){if(!(null!=t&&null!=e&&t.length>0&&e.length>0))throw new Error("Invalid RSA public key");this.n=Y(t,16),this.e=parseInt(e,16)}function X(t){return t.modPowInt(this.e,this.n)}function $(t){var e=J(t,this.n.bitLength()+7>>3);if(null==e)return null;var n=this.doPublic(e);if(null==n)return null;var i=n.toString(16);return 0==(1&i.length)?i:"0"+i}t.prototype.get=function(t){if(void 0==t&&(t=this.pos++),t>=this.enc.length)throw"Requesting byte offset "+t+" on a stream of length "+this.enc.length;return this.enc[t]},t.prototype.hexDigits="0123456789ABCDEF",t.prototype.hexByte=function(t){return this.hexDigits.charAt(t>>4&15)+this.hexDigits.charAt(15&t)},t.prototype.hexDump=function(t,e){for(var n="",i=t;e>i;++i)switch(n+=this.hexByte(this.get(i)),15&i){case 7:n+=" ";break;case 15:n+="\n";break;default:n+=" "}return n},t.prototype.parseStringISO=function(t,e){for(var n="",i=t;e>i;++i)n+=String.fromCharCode(this.get(i));return n},t.prototype.parseStringUTF=function(t,e){for(var n="",i=0,r=t;e>r;){var i=this.get(r++);n+=String.fromCharCode(128>i?i:i>191&&224>i?(31&i)<<6|63&this.get(r++):(15&i)<<12|(63&this.get(r++))<<6|63&this.get(r++))}return n},t.prototype.reTime=/^((?:1[89]|2\d)?\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/,t.prototype.parseTime=function(t,e){var n=this.parseStringISO(t,e),i=this.reTime.exec(n);return i?(n=i[1]+"-"+i[2]+"-"+i[3]+" "+i[4],i[5]&&(n+=":"+i[5],i[6]&&(n+=":"+i[6],i[7]&&(n+="."+i[7]))),i[8]&&(n+=" UTC","Z"!=i[8]&&(n+=i[8],i[9]&&(n+=":"+i[9]))),n):"Unrecognized time: "+n},t.prototype.parseInteger=function(t,e){var n=e-t;if(n>4){n<<=3;var i=this.get(t);if(0==i)n-=8;else for(;128>i;)i<<=1,--n;return"("+n+" bit)"}for(var r=0,o=t;e>o;++o)r=r<<8|this.get(o);return r},t.prototype.parseBitString=function(t,e){var n=this.get(t),i=(e-t-1<<3)-n,r="("+i+" bit)";if(20>=i){var o=n;r+=" ";for(var s=e-1;s>t;--s){for(var a=this.get(s),u=o;8>u;++u)r+=a>>u&1?"1":"0";o=0}}return r},t.prototype.parseOctetString=function(t,e){var n=e-t,i="("+n+" byte) ";n>20&&(e=t+20);for(var r=t;e>r;++r)i+=this.hexByte(this.get(r));return n>20&&(i+=String.fromCharCode(8230)),i},t.prototype.parseOID=function(t,e){for(var n,i=0,r=0,o=t;e>o;++o){var s=this.get(o);i=i<<7|127&s,r+=7,128&s||(void 0==n?n=parseInt(i/40)+"."+i%40:n+="."+(r>=31?"bigint":i),i=r=0),n+=String.fromCharCode()}return n},e.prototype.typeName=function(){if(void 0==this.tag)return"unknown";var t=this.tag>>6,e=(this.tag>>5&1,31&this.tag);switch(t){case 0:switch(e){case 0:return"EOC";case 1:return"BOOLEAN";case 2:return"INTEGER";case 3:return"BIT_STRING";case 4:return"OCTET_STRING";case 5:return"NULL";case 6:return"OBJECT_IDENTIFIER";case 7:return"ObjectDescriptor";case 8:return"EXTERNAL";case 9:return"REAL";case 10:return"ENUMERATED";case 11:return"EMBEDDED_PDV";case 12:return"UTF8String";case 16:return"SEQUENCE";case 17:return"SET";case 18:return"NumericString";case 19:return"PrintableString";case 20:return"TeletexString";case 21:return"VideotexString";case 22:return"IA5String";case 23:return"UTCTime";case 24:return"GeneralizedTime";case 25:return"GraphicString";case 26:return"VisibleString";case 27:return"GeneralString";case 28:return"UniversalString";case 30:return"BMPString";default:return"Universal_"+e.toString(16)}case 1:return"Application_"+e.toString(16);case 2:return"["+e+"]";case 3:return"Private_"+e.toString(16)}},e.prototype.content=function(){if(void 0==this.tag)return null;var t=this.tag>>6;if(0!=t)return null==this.sub?null:"("+this.sub.length+")";var e=31&this.tag,n=this.posContent(),i=Math.abs(this.length);switch(e){case 1:return 0==this.stream.get(n)?"false":"true";case 2:return this.stream.parseInteger(n,n+i);case 3:return this.sub?"("+this.sub.length+" elem)":this.stream.parseBitString(n,n+i);case 4:return this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(n,n+i);case 6:return this.stream.parseOID(n,n+i);case 16:case 17:return"("+this.sub.length+" elem)";case 12:return this.stream.parseStringUTF(n,n+i);case 18:case 19:case 20:case 21:case 22:case 26:return this.stream.parseStringISO(n,n+i);case 23:case 24:return this.stream.parseTime(n,n+i)}return null},e.prototype.toString=function(){return this.typeName()+"@"+this.stream.pos+"[header:"+this.header+",length:"+this.length+",sub:"+(null==this.sub?"null":this.sub.length)+"]"},e.prototype.print=function(t){if(void 0==t&&(t=""),document.writeln(t+this),null!=this.sub){t+=" ";for(var e=0,n=this.sub.length;n>e;++e)this.sub[e].print(t)}},e.prototype.toPrettyString=function(t){void 0==t&&(t="");var e=t+this.typeName()+" @"+this.stream.pos;if(this.length>=0&&(e+="+"),e+=this.length,32&this.tag?e+=" (constructed)":3!=this.tag&&4!=this.tag||null==this.sub||(e+=" (encapsulates)"),e+="\n",null!=this.sub){t+=" ";for(var n=0,i=this.sub.length;i>n;++n)e+=this.sub[n].toPrettyString(t)}return e},e.prototype.posStart=function(){return this.stream.pos},e.prototype.posContent=function(){return this.stream.pos+this.header},e.prototype.posEnd=function(){return this.stream.pos+this.header+Math.abs(this.length)},e.decodeLength=function(t){var e=t.get(),n=127&e;if(n==e)return n;if(n>3)throw"Length over 24 bits not supported at position "+(t.pos-1);if(0==n)return-1;e=0;for(var i=0;n>i;++i)e=e<<8|t.get();return e},e.hasContent=function(n,i,r){if(32&n)return!0;if(3>n||n>4)return!1;var o=new t(r);3==n&&o.get();var s=o.get();if(s>>6&1)return!1;try{var a=e.decodeLength(o);return o.pos-r.pos+a==i}catch(u){return!1}},e.decode=function(n){n instanceof t||(n=new t(n,0));var i=new t(n),r=n.get(),o=e.decodeLength(n),s=n.pos-i.pos,a=null;if(e.hasContent(r,o,n)){var u=n.pos;if(3==r&&n.get(),a=[],o>=0){for(var c=u+o;n.pos<c;)a[a.length]=e.decode(n);if(n.pos!=c)throw"Content size is not correct for container starting at offset "+u}else try{for(;;){var l=e.decode(n);if(0==l.tag)break;a[a.length]=l}o=u-n.pos}catch(p){throw"Exception while decoding undefined length content: "+p}}else n.pos+=o;return new e(i,s,o,r,a)};var te,ee="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ne="=",ie=0xdeadbeefcafe,re=15715070==(16777215&ie);re&&"Microsoft Internet Explorer"==navigator.appName?(o.prototype.am=u,te=30):re&&"Netscape"!=navigator.appName?(o.prototype.am=a,te=26):(o.prototype.am=c,te=28),o.prototype.DB=te,o.prototype.DM=(1<<te)-1,o.prototype.DV=1<<te;var oe=52;o.prototype.FV=Math.pow(2,oe),o.prototype.F1=oe-te,o.prototype.F2=2*te-oe;var se,ae,ue="0123456789abcdefghijklmnopqrstuvwxyz",ce=new Array;for(se="0".charCodeAt(0),ae=0;9>=ae;++ae)ce[se++]=ae;for(se="a".charCodeAt(0),ae=10;36>ae;++ae)ce[se++]=ae;for(se="A".charCodeAt(0),ae=10;36>ae;++ae)ce[se++]=ae;U.prototype.convert=R,U.prototype.revert=M,U.prototype.reduce=N,U.prototype.mulTo=D,U.prototype.sqrTo=F,B.prototype.convert=j,B.prototype.revert=z,B.prototype.reduce=V,B.prototype.mulTo=W,B.prototype.sqrTo=H,o.prototype.copyTo=h,o.prototype.fromInt=d,o.prototype.fromString=m,o.prototype.clamp=y,o.prototype.dlShiftTo=S,o.prototype.drShiftTo=C,o.prototype.lShiftTo=A,o.prototype.rShiftTo=x,o.prototype.subTo=T,o.prototype.multiplyTo=k,o.prototype.squareTo=P,o.prototype.divRemTo=I,o.prototype.invDigit=L,o.prototype.isEven=q,o.prototype.exp=Q,o.prototype.toString=g,o.prototype.negate=b,o.prototype.abs=v,o.prototype.compareTo=_,o.prototype.bitLength=E,o.prototype.mod=O,o.prototype.modPowInt=G,o.ZERO=f(0),o.ONE=f(1),Z.prototype.doPublic=X,Z.prototype.setPublic=K,Z.prototype.encrypt=$;var le={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(t){this.toString=function(){return"CORRUPT: "+this.message},this.message=t},invalid:function(t){this.toString=function(){return"INVALID: "+this.message},this.message=t},bug:function(t){this.toString=function(){return"BUG: "+this.message},this.message=t},notReady:function(t){this.toString=function(){return"NOT READY: "+this.message},this.message=t}}};"undefined"!=typeof module&&module.exports&&(module.exports=le),le.cipher.aes=function(t){this._tables[0][0][0]||this._precompute();var e,n,i,r,o,s=this._tables[0][4],a=this._tables[1],u=t.length,c=1;if(4!==u&&6!==u&&8!==u)throw new le.exception.invalid("invalid aes key size");for(this._key=[r=t.slice(0),o=[]],e=u;4*u+28>e;e++)i=r[e-1],(e%u===0||8===u&&e%u===4)&&(i=s[i>>>24]<<24^s[i>>16&255]<<16^s[i>>8&255]<<8^s[255&i],e%u===0&&(i=i<<8^i>>>24^c<<24,c=c<<1^283*(c>>7))),r[e]=r[e-u]^i;for(n=0;e;n++,e--)i=r[3&n?e:e-4],o[n]=4>=e||4>n?i:a[0][s[i>>>24]]^a[1][s[i>>16&255]]^a[2][s[i>>8&255]]^a[3][s[255&i]]},le.cipher.aes.prototype={encrypt:function(t){return this._crypt(t,0)},decrypt:function(t){return this._crypt(t,1)},_tables:[[[],[],[],[],[]],[[],[],[],[],[]]],_precompute:function(){var t,e,n,i,r,o,s,a,u,c=this._tables[0],l=this._tables[1],p=c[4],h=l[4],d=[],f=[];for(t=0;256>t;t++)f[(d[t]=t<<1^283*(t>>7))^t]=t;for(e=n=0;!p[e];e^=i||1,n=f[n]||1)for(s=n^n<<1^n<<2^n<<3^n<<4,s=s>>8^255&s^99,p[e]=s,h[s]=e,o=d[r=d[i=d[e]]],u=16843009*o^65537*r^257*i^16843008*e,a=257*d[s]^16843008*s,t=0;4>t;t++)c[t][e]=a=a<<24^a>>>8,l[t][s]=u=u<<24^u>>>8;for(t=0;5>t;t++)c[t]=c[t].slice(0),l[t]=l[t].slice(0)},_crypt:function(t,e){if(4!==t.length)throw new le.exception.invalid("invalid aes block size");var n,i,r,o,s=this._key[e],a=t[0]^s[0],u=t[e?3:1]^s[1],c=t[2]^s[2],l=t[e?1:3]^s[3],p=s.length/4-2,h=4,d=[0,0,0,0],f=this._tables[e],m=f[0],y=f[1],g=f[2],b=f[3],v=f[4];for(o=0;p>o;o++)n=m[a>>>24]^y[u>>16&255]^g[c>>8&255]^b[255&l]^s[h],i=m[u>>>24]^y[c>>16&255]^g[l>>8&255]^b[255&a]^s[h+1],r=m[c>>>24]^y[l>>16&255]^g[a>>8&255]^b[255&u]^s[h+2],l=m[l>>>24]^y[a>>16&255]^g[u>>8&255]^b[255&c]^s[h+3],h+=4,a=n,u=i,c=r;for(o=0;4>o;o++)d[e?3&-o:o]=v[a>>>24]<<24^v[u>>16&255]<<16^v[c>>8&255]<<8^v[255&l]^s[h++],n=a,a=u,u=c,c=l,l=n;return d}},le.bitArray={bitSlice:function(t,e,n){return t=le.bitArray._shiftRight(t.slice(e/32),32-(31&e)).slice(1),void 0===n?t:le.bitArray.clamp(t,n-e)},extract:function(t,e,n){var i,r=Math.floor(-e-n&31);return i=-32&(e+n-1^e)?t[e/32|0]<<32-r^t[e/32+1|0]>>>r:t[e/32|0]>>>r,i&(1<<n)-1},concat:function(t,e){if(0===t.length||0===e.length)return t.concat(e);var n=t[t.length-1],i=le.bitArray.getPartial(n);return 32===i?t.concat(e):le.bitArray._shiftRight(e,i,0|n,t.slice(0,t.length-1))},bitLength:function(t){var e,n=t.length;return 0===n?0:(e=t[n-1],32*(n-1)+le.bitArray.getPartial(e))},clamp:function(t,e){if(32*t.length<e)return t;t=t.slice(0,Math.ceil(e/32));var n=t.length;return e=31&e,n>0&&e&&(t[n-1]=le.bitArray.partial(e,t[n-1]&2147483648>>e-1,1)),t},partial:function(t,e,n){return 32===t?e:(n?0|e:e<<32-t)+1099511627776*t},getPartial:function(t){return Math.round(t/1099511627776)||32},equal:function(t,e){if(le.bitArray.bitLength(t)!==le.bitArray.bitLength(e))return!1;var n,i=0;for(n=0;n<t.length;n++)i|=t[n]^e[n];return 0===i},_shiftRight:function(t,e,n,i){var r,o,s=0;for(void 0===i&&(i=[]);e>=32;e-=32)i.push(n),n=0;if(0===e)return i.concat(t);for(r=0;r<t.length;r++)i.push(n|t[r]>>>e),n=t[r]<<32-e;return s=t.length?t[t.length-1]:0,o=le.bitArray.getPartial(s),i.push(le.bitArray.partial(e+o&31,e+o>32?n:i.pop(),1)),i},_xor4:function(t,e){return[t[0]^e[0],t[1]^e[1],t[2]^e[2],t[3]^e[3]]}},le.codec.hex={fromBits:function(t){var e,n="";for(e=0;e<t.length;e++)n+=((0|t[e])+0xf00000000000).toString(16).substr(4);return n.substr(0,le.bitArray.bitLength(t)/4)},toBits:function(t){var e,n,i=[];for(t=t.replace(/\s|0x/g,""),n=t.length,t+="00000000",e=0;e<t.length;e+=8)i.push(0^parseInt(t.substr(e,8),16));return le.bitArray.clamp(i,4*n)}},le.codec.utf8String={fromBits:function(t){var e,n,i="",r=le.bitArray.bitLength(t);for(e=0;r/8>e;e++)0===(3&e)&&(n=t[e/4]),i+=String.fromCharCode(n>>>24),n<<=8;return decodeURIComponent(escape(i))},toBits:function(t){t=unescape(encodeURIComponent(t));var e,n=[],i=0;for(e=0;e<t.length;e++)i=i<<8|t.charCodeAt(e),3===(3&e)&&(n.push(i),i=0);return 3&e&&n.push(le.bitArray.partial(8*(3&e),i)),n}},le.codec.base64={_chars:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(t,e,n){var i,r="",o=0,s=le.codec.base64._chars,a=0,u=le.bitArray.bitLength(t);for(n&&(s=s.substr(0,62)+"-_"),i=0;6*r.length<u;)r+=s.charAt((a^t[i]>>>o)>>>26),6>o?(a=t[i]<<6-o,o+=26,i++):(a<<=6,o-=6);for(;3&r.length&&!e;)r+="=";return r},toBits:function(t,e){t=t.replace(/\s|=/g,"");var n,i,r=[],o=0,s=le.codec.base64._chars,a=0;for(e&&(s=s.substr(0,62)+"-_"),n=0;n<t.length;n++){if(i=s.indexOf(t.charAt(n)),0>i)throw new le.exception.invalid("this isn't base64!");o>26?(o-=26,r.push(a^i>>>o),a=i<<32-o):(o+=6,a^=i<<32-o)}return 56&o&&r.push(le.bitArray.partial(56&o,a,1)),r}},le.codec.base64url={fromBits:function(t){return le.codec.base64.fromBits(t,1,1)},toBits:function(t){return le.codec.base64.toBits(t,1)}},void 0===le.beware&&(le.beware={}),le.beware["CBC mode is dangerous because it doesn't protect message integrity."]=function(){le.mode.cbc={name:"cbc",encrypt:function(t,e,n,i){if(i&&i.length)throw new le.exception.invalid("cbc can't authenticate data");if(128!==le.bitArray.bitLength(n))throw new le.exception.invalid("cbc iv must be 128 bits");var r,o=le.bitArray,s=o._xor4,a=o.bitLength(e),u=0,c=[];if(7&a)throw new le.exception.invalid("pkcs#5 padding only works for multiples of a byte");for(r=0;a>=u+128;r+=4,u+=128)n=t.encrypt(s(n,e.slice(r,r+4))),c.splice(r,0,n[0],n[1],n[2],n[3]);return a=16843009*(16-(a>>3&15)),n=t.encrypt(s(n,o.concat(e,[a,a,a,a]).slice(r,r+4))),c.splice(r,0,n[0],n[1],n[2],n[3]),c},decrypt:function(t,e,n,i){if(i&&i.length)throw new le.exception.invalid("cbc can't authenticate data");if(128!==le.bitArray.bitLength(n))throw new le.exception.invalid("cbc iv must be 128 bits");if(127&le.bitArray.bitLength(e)||!e.length)throw new le.exception.corrupt("cbc ciphertext must be a positive multiple of the block size");var r,o,s,a=le.bitArray,u=a._xor4,c=[];for(i=i||[],r=0;r<e.length;r+=4)o=e.slice(r,r+4),s=u(n,t.decrypt(o)),c.splice(r,0,s[0],s[1],s[2],s[3]),n=o;if(o=255&c[r-1],0==o||o>16)throw new le.exception.corrupt("pkcs#5 padding corrupt");if(s=16843009*o,!a.equal(a.bitSlice([s,s,s,s],0,8*o),a.bitSlice(c,32*c.length-8*o,32*c.length)))throw new le.exception.corrupt("pkcs#5 padding corrupt");return a.bitSlice(c,0,32*c.length-8*o)}}},le.misc.hmac=function(t,e){this._hash=e=e||le.hash.sha256;var n,i=[[],[]],r=e.prototype.blockSize/32;for(this._baseHash=[new e,new e],t.length>r&&(t=e.hash(t)),n=0;r>n;n++)i[0][n]=909522486^t[n],i[1][n]=1549556828^t[n];this._baseHash[0].update(i[0]),this._baseHash[1].update(i[1])},le.misc.hmac.prototype.encrypt=le.misc.hmac.prototype.mac=function(t,e){var n=new this._hash(this._baseHash[0]).update(t,e).finalize();return new this._hash(this._baseHash[1]).update(n).finalize()},le.hash.sha256=function(t){this._key[0]||this._precompute(),t?(this._h=t._h.slice(0),this._buffer=t._buffer.slice(0),this._length=t._length):this.reset()},le.hash.sha256.hash=function(t){return(new le.hash.sha256).update(t).finalize()},le.hash.sha256.prototype={blockSize:512,reset:function(){return this._h=this._init.slice(0),this._buffer=[],this._length=0,this},update:function(t){"string"==typeof t&&(t=le.codec.utf8String.toBits(t));var e,n=this._buffer=le.bitArray.concat(this._buffer,t),i=this._length,r=this._length=i+le.bitArray.bitLength(t);for(e=512+i&-512;r>=e;e+=512)this._block(n.splice(0,16));return this},finalize:function(){var t,e=this._buffer,n=this._h;for(e=le.bitArray.concat(e,[le.bitArray.partial(1,1)]),t=e.length+2;15&t;t++)e.push(0);for(e.push(Math.floor(this._length/4294967296)),e.push(0|this._length);e.length;)this._block(e.splice(0,16));return this.reset(),n},_init:[],_key:[],_precompute:function(){function t(t){return 4294967296*(t-Math.floor(t))|0}var e,n=0,i=2;t:for(;64>n;i++){for(e=2;i>=e*e;e++)if(i%e===0)continue t;8>n&&(this._init[n]=t(Math.pow(i,.5))),this._key[n]=t(Math.pow(i,1/3)),n++}},_block:function(t){var e,n,i,r,o=t.slice(0),s=this._h,a=this._key,u=s[0],c=s[1],l=s[2],p=s[3],h=s[4],d=s[5],f=s[6],m=s[7];for(e=0;64>e;e++)16>e?n=o[e]:(i=o[e+1&15],r=o[e+14&15],n=o[15&e]=(i>>>7^i>>>18^i>>>3^i<<25^i<<14)+(r>>>17^r>>>19^r>>>10^r<<15^r<<13)+o[15&e]+o[e+9&15]|0),n=n+m+(h>>>6^h>>>11^h>>>25^h<<26^h<<21^h<<7)+(f^h&(d^f))+a[e],m=f,f=d,d=h,h=p+n|0,p=l,l=c,c=u,u=n+(c&l^p&(c^l))+(c>>>2^c>>>13^c>>>22^c<<30^c<<19^c<<10)|0;s[0]=s[0]+u|0,s[1]=s[1]+c|0,s[2]=s[2]+l|0,s[3]=s[3]+p|0,s[4]=s[4]+h|0,s[5]=s[5]+d|0,s[6]=s[6]+f|0,s[7]=s[7]+m|0}},le.random={randomWords:function(t,e){var n,i,r=[],o=this.isReady(e);if(o===this._NOT_READY)throw new le.exception.notReady("generator isn't seeded");for(o&this._REQUIRES_RESEED&&this._reseedFromPools(!(o&this._READY)),n=0;t>n;n+=4)(n+1)%this._MAX_WORDS_PER_BURST===0&&this._gate(),i=this._gen4words(),r.push(i[0],i[1],i[2],i[3]);return this._gate(),r.slice(0,t)},setDefaultParanoia:function(t){this._defaultParanoia=t},addEntropy:function(t,e,n){n=n||"user";var i,r,o,s=(new Date).valueOf(),a=this._robins[n],u=this.isReady(),c=0;switch(i=this._collectorIds[n],void 0===i&&(i=this._collectorIds[n]=this._collectorIdNext++),void 0===a&&(a=this._robins[n]=0),this._robins[n]=(this._robins[n]+1)%this._pools.length,typeof t){case"number":void 0===e&&(e=1),this._pools[a].update([i,this._eventId++,1,e,s,1,0|t]);break;case"object":var l=Object.prototype.toString.call(t);if("[object Uint32Array]"===l){for(o=[],r=0;r<t.length;r++)o.push(t[r]);t=o}else for("[object Array]"!==l&&(c=1),r=0;r<t.length&&!c;r++)"number"!=typeof t[r]&&(c=1);if(!c){if(void 0===e)for(e=0,r=0;r<t.length;r++)for(o=t[r];o>0;)e++,o>>>=1;this._pools[a].update([i,this._eventId++,2,e,s,t.length].concat(t))}break;case"string":void 0===e&&(e=t.length),this._pools[a].update([i,this._eventId++,3,e,s,t.length]),this._pools[a].update(t);break;default:c=1}if(c)throw new le.exception.bug("random: addEntropy only supports number, array of numbers or string");this._poolEntropy[a]+=e,this._poolStrength+=e,u===this._NOT_READY&&(this.isReady()!==this._NOT_READY&&this._fireEvent("seeded",Math.max(this._strength,this._poolStrength)),this._fireEvent("progress",this.getProgress()))},isReady:function(t){var e=this._PARANOIA_LEVELS[void 0!==t?t:this._defaultParanoia];return this._strength&&this._strength>=e?this._poolEntropy[0]>this._BITS_PER_RESEED&&(new Date).valueOf()>this._nextReseed?this._REQUIRES_RESEED|this._READY:this._READY:this._poolStrength>=e?this._REQUIRES_RESEED|this._NOT_READY:this._NOT_READY},getProgress:function(t){var e=this._PARANOIA_LEVELS[t?t:this._defaultParanoia];return this._strength>=e?1:this._poolStrength>e?1:this._poolStrength/e},startCollectors:function(){if(!this._collectorsStarted){if(window.addEventListener)window.addEventListener("load",this._loadTimeCollector,!1),window.addEventListener("mousemove",this._mouseCollector,!1);else{if(!document.attachEvent)throw new le.exception.bug("can't attach event");document.attachEvent("onload",this._loadTimeCollector),document.attachEvent("onmousemove",this._mouseCollector)}this._collectorsStarted=!0}},stopCollectors:function(){this._collectorsStarted&&(window.removeEventListener?(window.removeEventListener("load",this._loadTimeCollector,!1),window.removeEventListener("mousemove",this._mouseCollector,!1)):window.detachEvent&&(window.detachEvent("onload",this._loadTimeCollector),window.detachEvent("onmousemove",this._mouseCollector)),this._collectorsStarted=!1)},addEventListener:function(t,e){this._callbacks[t][this._callbackI++]=e},removeEventListener:function(t,e){var n,i,r=this._callbacks[t],o=[];for(i in r)r.hasOwnProperty(i)&&r[i]===e&&o.push(i);for(n=0;n<o.length;n++)i=o[n],delete r[i]},_pools:[new le.hash.sha256],_poolEntropy:[0],_reseedCount:0,_robins:{},_eventId:0,_collectorIds:{},_collectorIdNext:0,_strength:0,_poolStrength:0,_nextReseed:0,_key:[0,0,0,0,0,0,0,0],_counter:[0,0,0,0],_cipher:void 0,_defaultParanoia:6,_collectorsStarted:!1,_callbacks:{progress:{},seeded:{}},_callbackI:0,_NOT_READY:0,_READY:1,_REQUIRES_RESEED:2,_MAX_WORDS_PER_BURST:65536,_PARANOIA_LEVELS:[0,48,64,96,128,192,256,384,512,768,1024],_MILLISECONDS_PER_RESEED:3e4,_BITS_PER_RESEED:80,_gen4words:function(){for(var t=0;4>t&&(this._counter[t]=this._counter[t]+1|0,!this._counter[t]);t++);return this._cipher.encrypt(this._counter)},_gate:function(){this._key=this._gen4words().concat(this._gen4words()),this._cipher=new le.cipher.aes(this._key)},_reseed:function(t){this._key=le.hash.sha256.hash(this._key.concat(t)),this._cipher=new le.cipher.aes(this._key);for(var e=0;4>e&&(this._counter[e]=this._counter[e]+1|0,!this._counter[e]);e++);},_reseedFromPools:function(t){var e,n=[],i=0;for(this._nextReseed=n[0]=(new Date).valueOf()+this._MILLISECONDS_PER_RESEED,e=0;16>e;e++)n.push(4294967296*Math.random()|0);for(e=0;e<this._pools.length&&(n=n.concat(this._pools[e].finalize()),i+=this._poolEntropy[e],this._poolEntropy[e]=0,t||!(this._reseedCount&1<<e));e++);this._reseedCount>=1<<this._pools.length&&(this._pools.push(new le.hash.sha256),this._poolEntropy.push(0)),this._poolStrength-=i,i>this._strength&&(this._strength=i),this._reseedCount++,this._reseed(n)},_mouseCollector:function(t){var e=t.x||t.clientX||t.offsetX||0,n=t.y||t.clientY||t.offsetY||0;le.random.addEntropy([e,n],2,"mouse")},_loadTimeCollector:function(){le.random.addEntropy((new Date).valueOf(),2,"loadtime")},_fireEvent:function(t,e){var n,i=le.random._callbacks[t],r=[];for(n in i)i.hasOwnProperty(n)&&r.push(i[n]);for(n=0;n<r.length;n++)r[n](e)}},function(){try{var t=new Uint32Array(32);crypto.getRandomValues(t),le.random.addEntropy(t,1024,"crypto.getRandomValues")}catch(e){}}(),function(){for(var t in le.beware)le.beware.hasOwnProperty(t)&&le.beware[t]()}();var pe={sjcl:le,version:"1.3.10"};pe.generateAesKey=function(){return{key:le.random.randomWords(8,0),encrypt:function(t){return this.encryptWithIv(t,le.random.randomWords(4,0))},encryptWithIv:function(t,e){var n=new le.cipher.aes(this.key),i=le.codec.utf8String.toBits(t),r=le.mode.cbc.encrypt(n,i,e),o=le.bitArray.concat(e,r);return le.codec.base64.fromBits(o)}}},pe.create=function(t){return new pe.EncryptionClient(t)},pe.EncryptionClient=function(t){var i=this,o=[];i.publicKey=t,i.version=pe.version;var s=function(t,e){var n,i,r;n=document.createElement(t);for(i in e)e.hasOwnProperty(i)&&(r=e[i],n.setAttribute(i,r));return n},a=function(t){return window.jQuery&&t instanceof jQuery?t[0]:t.nodeType&&1===t.nodeType?t:document.getElementById(t)},u=function(t){var e,n,i,r,o=[];if("INTEGER"===t.typeName()&&(e=t.posContent(),n=t.posEnd(),i=t.stream.hexDump(e,n).replace(/[ \n]/g,""),o.push(i)),null!==t.sub)for(r=0;r<t.sub.length;r++)o=o.concat(u(t.sub[r]));return o},c=function(t){var e,n,i=[],r=t.children;for(n=0;n<r.length;n++)e=r[n],1===e.nodeType&&e.attributes["data-encrypted-name"]?i.push(e):e.children&&e.children.length>0&&(i=i.concat(c(e)));return i},l=function(){var n,i,o,s,a,c;try{a=r(t),n=e.decode(a)}catch(l){throw"Invalid encryption key. Please use the key labeled 'Client-Side Encryption Key'"}if(o=u(n),2!==o.length)throw"Invalid encryption key. Please use the key labeled 'Client-Side Encryption Key'";return s=o[0],i=o[1],c=new Z,c.setPublic(s,i),c},p=function(){return{key:le.random.randomWords(8,0),sign:function(t){var e=new le.misc.hmac(this.key,le.hash.sha256),n=e.encrypt(t);return le.codec.base64.fromBits(n)}}};i.encrypt=function(t){var e=l(),r=pe.generateAesKey(),o=p(),s=r.encrypt(t),a=o.sign(le.codec.base64.toBits(s)),u=le.bitArray.concat(r.key,o.key),c=le.codec.base64.fromBits(u),h=e.encrypt(c),d="$bt4|javascript_"+i.version.replace(/\./g,"_")+"$",f=null;return h&&(f=n(h)),d+f+"$"+s+"$"+a},i.encryptForm=function(t){var e,n,r,u,l,p;for(t=a(t),p=c(t);o.length>0;){try{t.removeChild(o[0])}catch(h){}o.splice(0,1)}for(l=0;l<p.length;l++)e=p[l],r=e.getAttribute("data-encrypted-name"),n=i.encrypt(e.value),e.removeAttribute("name"),u=s("input",{value:n,type:"hidden",name:r}),o.push(u),t.appendChild(u)},i.onSubmitEncryptForm=function(t,e){var n;t=a(t),n=function(n){return i.encryptForm(t),e?e(n):n},window.jQuery?window.jQuery(t).submit(n):t.addEventListener?t.addEventListener("submit",n,!1):t.attachEvent&&t.attachEvent("onsubmit",n)},i.formEncrypter={encryptForm:i.encryptForm,extractForm:a,onSubmitEncryptForm:i.onSubmitEncryptForm},le.random.startCollectors()},window.Braintree=pe
|
2 |
+
}(),!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.braintree=t()}}(function(){var define,module,exports;return function t(e,n,i){function r(s,a){if(!n[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[s]={exports:{}};e[s][0].call(l.exports,function(t){var n=e[s][1][t];return r(n?n:t)},l,l.exports,t,e,n,i)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s<i.length;s++)r(i[s]);return r}({1:[function(t,e){"use strict";t("./src/rpc-dispatcher")(),e.exports=t("./src/setup.js")},{"./src/rpc-dispatcher":308,"./src/setup.js":309}],2:[function(t,e){(function(n){"use strict";function i(t,e){return t.status>=400?[t,null]:[null,e(t)]}function r(t){var e;this.attrs={},t.hasOwnProperty("sharedCustomerIdentifier")&&(this.attrs.sharedCustomerIdentifier=t.sharedCustomerIdentifier),e=c(t.clientToken),this.driver=t.driver||l,this.authUrl=e.authUrl,this.analyticsUrl=e.analytics?e.analytics.url:void 0,this.clientApiUrl=e.clientApiUrl,this.customerId=t.customerId,this.challenges=e.challenges,this.integration=t.integration||"";var n=u.create(this,{container:t.container,clientToken:e});this.verify3DS=a.bind(n.verify,n),this.attrs.authorizationFingerprint=e.authorizationFingerprint,this.attrs.sharedCustomerIdentifierType=t.sharedCustomerIdentifierType,e.merchantAccountId&&(this.attrs.merchantAccountId=e.merchantAccountId),this.timeoutWatchers=[],this.requestTimeout=t.hasOwnProperty("timeout")?t.timeout:6e4}function o(){}function s(t,e){var n,i={};for(n in t)t.hasOwnProperty(n)&&(i[n]=t[n]);for(n in e)e.hasOwnProperty(n)&&(i[n]=e[n]);return i}var a=t("braintree-utilities"),u=t("braintree-3ds"),c=t("./parse-client-token"),l=t("./jsonp-driver"),p=t("./util"),h=t("./sepa-mandate"),d=t("./sepa-bank-account"),f=t("./credit-card"),m=t("./coinbase-account"),y=t("./root-data"),g=t("./normalize-api-fields").normalizeCreditCardFields;r.prototype.requestWithTimeout=function(t,e,n,r,s){s=s||o;var a,u,c=this;y.get(function(o){u="braintree/web/"+o.sdkVersion,e.braintreeLibraryVersion=u,e.hasOwnProperty("analytics")&&e.hasOwnProperty("_meta")&&(e._meta.sdkVersion=u,e._meta.merchantAppId=o.merchantAppId),a=r(t,e,function(t,e){if(c.timeoutWatchers[e]){clearTimeout(c.timeoutWatchers[e]);var r=i(t,function(t){return n(t)});s.apply(null,r)}}),c.requestTimeout>0?this.timeoutWatchers[a]=setTimeout(function(){c.timeoutWatchers[a]=null,s.apply(null,[{errors:"Unknown error"},null])},c.requestTimeout):s.apply(null,[{errors:"Unknown error"},null])},this)},r.prototype.post=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.post,i)},r.prototype.get=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.get,i)},r.prototype.put=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.put,i)},r.prototype.getCreditCards=function(t){this.get(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods"]),this.attrs,function(t){var e=0,n=t.paymentMethods.length,i=[];for(e;n>e;e++)i.push(new f(t.paymentMethods[e]));return i},t)},r.prototype.tokenizeCoinbase=function(t,e){t.options={validate:!1},this.addCoinbase(t,function(t,n){t?e(t,null):n&&n.nonce?e(t,n):e("Unable to tokenize coinbase account.",null)})},r.prototype.tokenizeCard=function(t,e){t.options={validate:!1},this.addCreditCard(t,function(t,n){n&&n.nonce?e(t,n.nonce,{type:n.type,details:n.details}):e("Unable to tokenize card.",null)})},r.prototype.lookup3DS=function(t,e){var n=p.joinUrlFragments([this.clientApiUrl,"v1/payment_methods",t.nonce,"three_d_secure/lookup"]),i=s(this.attrs,{amount:t.amount});this.post(n,i,function(t){return t},e)},r.prototype.addSEPAMandate=function(t,e){var n=s(this.attrs,{sepaMandate:t});this.post(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates.json"]),n,function(t){return new h(t.sepaMandates[0])},e)},r.prototype.acceptSEPAMandate=function(t,e){this.put(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates",t,"accept"]),this.attrs,function(t){return new d(t.sepaBankAccounts[0])},e)},r.prototype.getSEPAMandate=function(t,e){var n;n=t.paymentMethodToken?s(this.attrs,{paymentMethodToken:t.paymentMethodToken}):this.attrs,this.get(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates",t.mandateReferenceNumber||""]),n,function(t){return new h(t.sepaMandates[0])},e)},r.prototype.addCoinbase=function(t,e){var n;delete t.share,n=s(this.attrs,{coinbaseAccount:t,_meta:{integration:this.integration||"custom",source:"coinbase"}}),this.post(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/coinbase_accounts"]),n,function(t){return new m(t.coinbaseAccounts[0])},e)},r.prototype.addCreditCard=function(t,e){var n,i=t.share;delete t.share;var r=g(t);n=s(this.attrs,{share:i,creditCard:r,_meta:{integration:this.integration||"custom",source:"form"}}),this.post(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/credit_cards"]),n,function(t){return new f(t.creditCards[0])},e)},r.prototype.unlockCreditCard=function(t,e,n){var i=s(this.attrs,{challengeResponses:e});this.put(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/",t.nonce]),i,function(t){return new f(t.paymentMethods[0])},n)},r.prototype.sendAnalyticsEvents=function(t,e){var i,r=this.analyticsUrl,o=[];if(t=p.isArray(t)?t:[t],!r)return void(e&&e.apply(null,[null,{}]));for(var a in t)t.hasOwnProperty(a)&&o.push({kind:t[a]});i=s(this.attrs,{analytics:o,_meta:{platform:"web",platformVersion:n.navigator.userAgent,integrationType:this.integration}}),this.post(r,i,function(t){return t},e)},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./coinbase-account":3,"./credit-card":4,"./jsonp-driver":5,"./normalize-api-fields":7,"./parse-client-token":8,"./root-data":10,"./sepa-bank-account":11,"./sepa-mandate":12,"./util":13,"braintree-3ds":22,"braintree-utilities":41}],3:[function(t,e){"use strict";function n(t){for(var e=0;e<i.length;e++){var n=i[e];this[n]=t[n]}}var i=["nonce","type","description","details"];e.exports=n},{}],4:[function(t,e){"use strict";function n(t){for(var e=0;e<i.length;e++){var n=i[e];this[n]=t[n]}}var i=["billingAddress","branding","createdAt","createdAtMerchant","createdAtMerchantName","details","isLocked","lastUsedAt","lastUsedAtMerchant","lastUsedAtMerchantName","lastUsedByCurrentMerchant","nonce","securityQuestions","type"];e.exports=n},{}],5:[function(t,e){"use strict";function n(t,e,n){return o.get(t,e,n)}function i(t,e,n){return e._method="POST",o.get(t,e,n)}function r(t,e,n){return e._method="PUT",o.get(t,e,n)}var o=t("./jsonp");e.exports={get:n,post:i,put:r}},{"./jsonp":6}],6:[function(t,e){(function(n){"use strict";function i(t,e){var n=document.createElement("script"),i=!1;n.src=t,n.async=!0;var r=e||l.error;"function"==typeof r&&(n.onerror=function(e){r({url:t,event:e})}),n.onload=n.onreadystatechange=function(){i||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState||(i=!0,n.onload=n.onreadystatechange=null,n&&n.parentNode&&n.parentNode.removeChild(n))},a||(a=document.getElementsByTagName("head")[0]),a.appendChild(n)}function r(t,e){var n,i,o,s=[];for(var o in t)t.hasOwnProperty(o)&&(i=t[o],n=e?u.isArray(t)?e+"[]":e+"["+o+"]":o,s.push("object"==typeof i?r(i,n):encodeURIComponent(n)+"="+encodeURIComponent(i)));return s.join("&")}function o(t,e,n,o){var s=-1===(t||"").indexOf("?")?"?":"&";o=o||l.callbackName||"callback";var a=o+"_json"+u.generateUUID();return s+=r(e),c[a]=function(t){n(t,a);try{delete c[a]}catch(e){}c[a]=null},i(t+s+"&"+o+"="+a),a}function s(t){l=t}var a,u=t("./util"),c=n,l={};e.exports={get:o,init:s,stringify:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./util":13}],7:[function(t,e){"use strict";function n(t){var e={billingAddress:t.billingAddress||{}};for(var n in t)if(t.hasOwnProperty(n))switch(n.replace(/_/,"").toLowerCase()){case"postalcode":case"countryname":case"countrycodenumeric":case"countrycodealpha2":case"countrycodealpha3":case"region":case"extendedaddress":case"locality":case"firstname":case"lastname":case"company":case"streetaddress":e.billingAddress[n]=t[n];break;default:e[n]=t[n]}return e}e.exports={normalizeCreditCardFields:n}},{}],8:[function(t,e){"use strict";function n(t){var e;if(!t)throw new Error("Braintree API Client Misconfigured: clientToken required.");if("object"==typeof t&&null!==t)e=t;else{try{t=window.atob(t)}catch(n){}try{e=JSON.parse(t)}catch(i){throw new Error("Braintree API Client Misconfigured: clientToken is invalid.")}}if(!e.hasOwnProperty("authUrl")||!e.hasOwnProperty("clientApiUrl"))throw new Error("Braintree API Client Misconfigured: clientToken is invalid.");return e}t("./polyfill"),e.exports=n},{"./polyfill":9}],9:[function(){(function(t){"use strict";t.atob=t.atob||function(t){var e=new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})([=]{1,2})?$"),n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i="";if(!e.test(t))throw new Error("Braintree API Client Misconfigured: clientToken is invalid.");var r=0;do{var o=n.indexOf(t.charAt(r++)),s=n.indexOf(t.charAt(r++)),a=n.indexOf(t.charAt(r++)),u=n.indexOf(t.charAt(r++)),c=(63&o)<<2|s>>4&3,l=(15&s)<<4|a>>2&15,p=(3&a)<<6|63&u;i+=String.fromCharCode(c)+(l?String.fromCharCode(l):"")+(p?String.fromCharCode(p):"")}while(r<t.length);return i}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],10:[function(t,e){(function(n){"use strict";function i(){var t=n.braintree;return t&&t.hasOwnProperty("VERSION")?t.VERSION:void 0}function r(t,e){null==s?(h.push({callback:t,context:e}),p===!1&&(a=setTimeout(function(){o(d)},200),l.invoke("getExternalData",[],o),p=!0)):t.call(e,s)}function o(t){clearTimeout(a),s={sdkVersion:t.sdkVersion,merchantAppId:t.merchantAppId};for(var e=0;e<h.length;e++){var n=h[e];n.callback.call(n.context,s)}h=[]}var s,a,u=t("braintree-rpc"),c=new u.MessageBus(window),l=new u.RPCClient(c,window.parent),p=!1,h=[],d={sdkVersion:i(),merchantAppId:n.location.href};e.exports={get:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"braintree-rpc":30}],11:[function(t,e){"use strict";function n(t){for(var e=0;e<i.length;e++){var n=i[e];this[n]=t[n]}}var i=["bic","maskedIBAN","nonce","accountHolderName"];e.exports=n},{}],12:[function(t,e){"use strict";function n(t){for(var e=0;e<i.length;e++){var n=i[e];this[n]=t[n]}}var i=["accountHolderName","bic","longFormURL","mandateReferenceNumber","maskedIBAN","shortForm"];e.exports=n},{}],13:[function(t,e){"use strict";function n(t){var e,n,i=[];for(n=0;n<t.length;n++)e=t[n],"/"===e.charAt(e.length-1)&&(e=e.substring(0,e.length-1)),"/"===e.charAt(0)&&(e=e.substring(1)),i.push(e);return i.join("/")}function i(t){return t&&"object"==typeof t&&"number"==typeof t.length&&"[object Array]"===Object.prototype.toString.call(t)||!1}function r(){return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=Math.floor(16*Math.random()),n="x"===t?e:3&e|8;return n.toString(16)})}e.exports={joinUrlFragments:n,isArray:i,generateUUID:r}},{}],14:[function(t,e){"use strict";function n(t){return new i(t)}var i=t("./lib/client"),r=t("./lib/jsonp"),o=t("./lib/jsonp-driver"),s=t("./lib/util"),a=t("./lib/parse-client-token");e.exports={Client:i,configure:n,util:s,JSONP:r,JSONPDriver:o,parseClientToken:a}},{"./lib/client":2,"./lib/jsonp":6,"./lib/jsonp-driver":5,"./lib/parse-client-token":8,"./lib/util":13}],15:[function(t,e){"use strict";function n(t,e){if(e=e||"["+t+"] is not a valid DOM Element",t&&t.nodeType&&1===t.nodeType)return t;if(t&&window.jQuery&&(t instanceof jQuery||"jquery"in Object(t))&&0!==t.length)return t[0];if("string"==typeof t&&document.getElementById(t))return document.getElementById(t);throw new Error(e)}e.exports={normalizeElement:n}},{}],16:[function(t,e){"use strict";function n(t,e,n,i){t.addEventListener?t.addEventListener(e,n,i):t.attachEvent&&t.attachEvent("on"+e,n)}function i(t,e,n,i){t.removeEventListener?t.removeEventListener(e,n,i):t.detachEvent&&t.detachEvent("on"+e,n)}e.exports={addEventListener:n,removeEventListener:i}},{}],17:[function(t,e){"use strict";function n(t){return"[object Function]"===r.call(t)}function i(t,e){return function(){t.apply(e,arguments)}}var r=Object.prototype.toString;e.exports={bind:i,isFunction:n}},{}],18:[function(t,e){"use strict";function n(){return"https:"===window.location.protocol}function i(t){switch(t){case null:case void 0:return"";case!0:return"1";case!1:return"0";default:return encodeURIComponent(t)}}function r(t,e){var n,o,s=[];for(o in t)if(t.hasOwnProperty(o)){var a=t[o];n=e?e+"["+o+"]":o,"object"==typeof a?s.push(r(a,n)):void 0!==a&&null!==a&&s.push(i(n)+"="+i(a))}return s.join("&")}function o(t){for(var e={},n=t.split("&"),i=0;i<n.length;i++){var r=n[i].split("="),o=r[0],s=decodeURIComponent(r[1]);e[o]=s}return e}function s(t){var e=t.split("?");return 2!==e.length?{}:o(e[1])}e.exports={isBrowserHttps:n,makeQueryString:r,decodeQueryString:o,getParams:s}},{}],19:[function(t,e){var n=t("./lib/dom"),i=t("./lib/url"),r=t("./lib/fn"),o=t("./lib/events");e.exports={normalizeElement:n.normalizeElement,isBrowserHttps:i.isBrowserHttps,makeQueryString:i.makeQueryString,decodeQueryString:i.decodeQueryString,getParams:i.getParams,removeEventListener:o.removeEventListener,addEventListener:o.addEventListener,bind:r.bind,isFunction:r.isFunction}},{"./lib/dom":15,"./lib/events":16,"./lib/fn":17,"./lib/url":18}],20:[function(t,e){"use strict";function n(t,e){var n=window.getComputedStyle?getComputedStyle(t):t.currentStyle;return n[e]}function i(){return{html:{height:o.style.height||"",overflow:n(o,"overflow"),position:n(o,"position")},body:{height:s.style.height||"",overflow:n(s,"overflow")}}}function r(t,e){this.assetsUrl=t,this.container=e||document.body,this.iframe=null,o=document.documentElement,s=document.body,this.merchantPageDefaultStyles=i()}var o,s,a=t("braintree-utilities"),u=t("../shared/receiver"),c="1.2.0";r.prototype.get=function(t,e){var n=this,i=this.constructAuthorizationURL(t);this.container&&a.isFunction(this.container)?this.container(i+"&no_style=1"):this.insertIframe(i),new u(function(t){a.isFunction(n.container)||n.removeIframe(),e(t)})},r.prototype.removeIframe=function(){this.container&&this.container.nodeType&&1===this.container.nodeType?this.container.removeChild(this.iframe):this.container&&window.jQuery&&this.container instanceof jQuery?$(this.iframe,this.container).remove():"string"==typeof this.container&&document.getElementById(this.container).removeChild(this.iframe),this.unlockMerchantWindowSize()},r.prototype.insertIframe=function(t){var e=document.createElement("iframe");if(e.src=t,this.applyStyles(e),this.lockMerchantWindowSize(),this.container&&this.container.nodeType&&1===this.container.nodeType)this.container.appendChild(e);else if(this.container&&window.jQuery&&this.container instanceof jQuery&&0!==this.container.length)this.container.append(e);else{if("string"!=typeof this.container||!document.getElementById(this.container))throw new Error("Unable to find valid container for iframe.");document.getElementById(this.container).appendChild(e)}this.iframe=e},r.prototype.applyStyles=function(t){t.style.position="fixed",t.style.top="0",t.style.left="0",t.style.height="100%",t.style.width="100%",t.setAttribute("frameborder","0"),t.setAttribute("allowTransparency","true"),t.style.border="0",t.style.zIndex="99999"},r.prototype.lockMerchantWindowSize=function(){o.style.overflow="hidden",s.style.overflow="hidden",s.style.height="100%"},r.prototype.unlockMerchantWindowSize=function(){var t=this.merchantPageDefaultStyles;s.style.height=t.body.height,s.style.overflow=t.body.overflow,o.style.overflow=t.html.overflow},r.prototype.constructAuthorizationURL=function(t){var e,n=window.location.href;return n.indexOf("#")>-1&&(n=n.split("#")[0]),e=a.makeQueryString({acsUrl:t.acsUrl,pareq:t.pareq,termUrl:t.termUrl+"&three_d_secure_version="+c,md:t.md,parentUrl:n}),this.assetsUrl+"/3ds/"+c+"/html/style_frame?"+e},e.exports=r},{"../shared/receiver":24,"braintree-utilities":19}],21:[function(t,e){"use strict";function n(){}function i(t,e){e=e||{},this.clientToken=e.clientToken,this.container=e.container,this.api=t,this.nonce=null,this._boundHandleUserClose=r.bind(this._handleUserClose,this)}var r=t("braintree-utilities"),o=t("./authorization_service");i.prototype.verify=function(t,e){if(!r.isFunction(e))throw this.api.sendAnalyticsEvents("3ds.web.no_callback"),new Error("No suitable callback argument was given");r.isFunction(t.onUserClose)&&(this._onUserClose=t.onUserClose);var n={nonce:"",amount:t.amount},i=t.creditCard;if("string"==typeof i)n.nonce=i,this.api.sendAnalyticsEvents("3ds.web.verify.nonce"),this.startVerification(n,e);else{var o=this,s=function(t,i){return t?e(t):(n.nonce=i,void o.startVerification(n,e))};this.api.sendAnalyticsEvents("3ds.web.verify.credit_card"),this.api.tokenizeCard(i,s)}},i.prototype.startVerification=function(t,e){this.api.lookup3DS(t,r.bind(this.handleLookupResponse(e),this))},i.prototype.handleLookupResponse=function(t){var e=this;return function(n,i){var s;n?t(n.error):i.lookup&&i.lookup.acsUrl&&i.lookup.acsUrl.length>0?(e.nonce=i.paymentMethod.nonce,s=new o(this.clientToken.assetsUrl,this.container),s.get(i.lookup,r.bind(this.handleAuthenticationResponse(t),this)),this._detachListeners(),this._attachListeners()):(e.nonce=i.paymentMethod.nonce,t(null,{nonce:e.nonce,verificationDetails:i.threeDSecureInfo}))}},i.prototype.handleAuthenticationResponse=function(t){return function(e){var n,i=r.decodeQueryString(e);i.user_closed||(n=JSON.parse(i.auth_response),n.success?t(null,{nonce:n.paymentMethod.nonce,verificationDetails:n.threeDSecureInfo}):n.threeDSecureInfo&&n.threeDSecureInfo.liabilityShiftPossible?t(null,{nonce:this.nonce,verificationDetails:n.threeDSecureInfo}):t(n.error))}},i.prototype._attachListeners=function(){r.addEventListener(window,"message",this._boundHandleUserClose)},i.prototype._detachListeners=function(){r.removeEventListener(window,"message",this._boundHandleUserClose)},i.prototype._handleUserClose=function(t){"user_closed=true"===t.data&&this._onUserClose()},i.prototype._onUserClose=n,e.exports=i},{"./authorization_service":20,"braintree-utilities":19}],22:[function(t,e){"use strict";var n=t("./client");t("./vendor/json2"),e.exports={create:function(t,e){var i=new n(t,e);return i}}},{"./client":21,"./vendor/json2":23}],23:[function(require,module,exports){"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return 10>t?"0"+t:t}function quote(t){return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var n,i,r,o,s,a=gap,u=e[t];switch(u&&"object"==typeof u&&"function"==typeof u.toJSON&&(u=u.toJSON(t)),"function"==typeof rep&&(u=rep.call(e,t,u)),typeof u){case"string":return quote(u);case"number":return isFinite(u)?String(u):"null";case"boolean":case"null":return String(u);case"object":if(!u)return"null";if(gap+=indent,s=[],"[object Array]"===Object.prototype.toString.apply(u)){for(o=u.length,n=0;o>n;n+=1)s[n]=str(n,u)||"null";return r=0===s.length?"[]":gap?"[\n"+gap+s.join(",\n"+gap)+"\n"+a+"]":"["+s.join(",")+"]",gap=a,r}if(rep&&"object"==typeof rep)for(o=rep.length,n=0;o>n;n+=1)"string"==typeof rep[n]&&(i=rep[n],r=str(i,u),r&&s.push(quote(i)+(gap?": ":":")+r));else for(i in u)Object.prototype.hasOwnProperty.call(u,i)&&(r=str(i,u),r&&s.push(quote(i)+(gap?": ":":")+r));return r=0===s.length?"{}":gap?"{\n"+gap+s.join(",\n"+gap)+"\n"+a+"}":"{"+s.join(",")+"}",gap=a,r}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;"function"!=typeof JSON.stringify&&(JSON.stringify=function(t,e,n){var i;if(gap="",indent="","number"==typeof n)for(i=0;n>i;i+=1)indent+=" ";else"string"==typeof n&&(indent=n);if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(t,e){var n,i,r=t[e];if(r&&"object"==typeof r)for(n in r)Object.prototype.hasOwnProperty.call(r,n)&&(i=walk(r,n),void 0!==i?r[n]=i:delete r[n]);return reviver.call(t,e,r)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}()},{}],24:[function(t,e){"use strict";function n(t){this.postMessageReceiver(t),this.hashChangeReceiver(t)}var i=t("braintree-utilities");n.prototype.postMessageReceiver=function(t){var e=this;this.wrappedCallback=function(n){var i=n.data;(/^(auth_response=)/.test(i)||"user_closed=true"===i)&&(t(i),e.stopListening())},i.addEventListener(window,"message",this.wrappedCallback)},n.prototype.hashChangeReceiver=function(t){var e,n=window.location.hash,i=this;this.poll=setInterval(function(){e=window.location.hash,e.length>0&&e!==n&&(i.stopListening(),e=e.substring(1,e.length),t(e),window.location.hash=n.length>0?n:"")},10)},n.prototype.stopListening=function(){clearTimeout(this.poll),i.removeEventListener(window,"message",this.wrappedCallback)},e.exports=n},{"braintree-utilities":19}],25:[function(t,e){"use strict";function n(t){this.host=t||window,this.handlers=[],i.addEventListener(this.host,"message",i.bind(this.receive,this))}var i=t("braintree-utilities");n.prototype.receive=function(t){var e,i,r,o;try{r=JSON.parse(t.data)}catch(s){return}for(o=r.type,i=new n.Message(this,t.source,r.data),e=0;e<this.handlers.length;e++)this.handlers[e].type===o&&this.handlers[e].handler(i)},n.prototype.send=function(t,e,n){t.postMessage(JSON.stringify({type:e,data:n}),"*")},n.prototype.register=function(t,e){this.handlers.push({type:t,handler:e})},n.prototype.unregister=function(t,e){for(var n=this.handlers.length-1;n>=0;n--)if(this.handlers[n].type===t&&this.handlers[n].handler===e)return this.handlers.splice(n,1)},n.Message=function(t,e,n){this.bus=t,this.source=e,this.content=n},n.Message.prototype.reply=function(t,e){this.bus.send(this.source,t,e)},e.exports=n},{"braintree-utilities":35}],26:[function(t,e){"use strict";function n(t,e){this.bus=t,this.target=e,this.handlers=[],this.bus.register("publish",i.bind(this._handleMessage,this))}var i=t("braintree-utilities");n.prototype._handleMessage=function(t){var e,n=t.content,i=this.handlers[n.channel];if("undefined"!=typeof i)for(e=0;e<i.length;e++)i[e](n.data)},n.prototype.publish=function(t,e){this.bus.send(this.target,"publish",{channel:t,data:e})},n.prototype.subscribe=function(t,e){this.handlers[t]=this.handlers[t]||[],this.handlers[t].push(e)},n.prototype.unsubscribe=function(t,e){var n,i=this.handlers[t];if("undefined"!=typeof i)for(n=0;n<i.length;n++)i[n]===e&&i.splice(n,1)},e.exports=n},{"braintree-utilities":35}],27:[function(t,e){"use strict";function n(t){this.bus=t,this.frames=[],this.handlers=[]}n.prototype.subscribe=function(t,e){this.handlers[t]=this.handlers[t]||[],this.handlers[t].push(e)},n.prototype.registerFrame=function(t){this.frames.push(t)},n.prototype.unregisterFrame=function(t){for(var e=0;e<this.frames.length;e++)this.frames[e]===t&&this.frames.splice(e,1)},n.prototype.publish=function(t,e){var n,i=this.handlers[t];if("undefined"!=typeof i)for(n=0;n<i.length;n++)i[n](e);for(n=0;n<this.frames.length;n++)this.bus.send(this.frames[n],"publish",{channel:t,data:e})},n.prototype.unsubscribe=function(t,e){var n,i=this.handlers[t];if("undefined"!=typeof i)for(n=0;n<i.length;n++)i[n]===e&&i.splice(n,1)},e.exports=n},{}],28:[function(t,e){"use strict";function n(t,e){this.bus=t,this.target=e||window.parent,this.counter=0,this.callbacks={},this.bus.register("rpc_response",i.bind(this._handleResponse,this))}var i=t("braintree-utilities");n.prototype._handleResponse=function(t){var e=t.content,n=this.callbacks[e.id];"function"==typeof n&&(n.apply(null,e.response),delete this.callbacks[e.id])},n.prototype.invoke=function(t,e,n){var i=this.counter++;this.callbacks[i]=n,this.bus.send(this.target,"rpc_request",{id:i,method:t,args:e})},e.exports=n},{"braintree-utilities":35}],29:[function(t,e){"use strict";function n(t){this.bus=t,this.methods={},this.bus.register("rpc_request",i.bind(this._handleRequest,this))}var i=t("braintree-utilities");n.prototype._handleRequest=function(t){var e,n=t.content,i=n.args||[],r=this.methods[n.method];"function"==typeof r&&(e=function(){t.reply("rpc_response",{id:n.id,response:Array.prototype.slice.call(arguments)})},i.push(e),r.apply(null,i))},n.prototype.define=function(t,e){this.methods[t]=e},e.exports=n},{"braintree-utilities":35}],30:[function(t,e){var n=t("./lib/message-bus"),i=t("./lib/pubsub-client"),r=t("./lib/pubsub-server"),o=t("./lib/rpc-client"),s=t("./lib/rpc-server");e.exports={MessageBus:n,PubsubClient:i,PubsubServer:r,RPCClient:o,RPCServer:s}},{"./lib/message-bus":25,"./lib/pubsub-client":26,"./lib/pubsub-server":27,"./lib/rpc-client":28,"./lib/rpc-server":29}],31:[function(t,e){"use strict";function n(t,e){if(e=e||"["+t+"] is not a valid DOM Element",t&&t.nodeType&&1===t.nodeType)return t;if(t&&window.jQuery&&t instanceof jQuery&&0!==t.length)return t[0];if("string"==typeof t&&document.getElementById(t))return document.getElementById(t);throw new Error(e)}e.exports={normalizeElement:n}},{}],32:[function(t,e){"use strict";function n(t,e,n){t.addEventListener?t.addEventListener(e,n,!1):t.attachEvent&&t.attachEvent("on"+e,n)}function i(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent&&t.detachEvent("on"+e,n)}e.exports={removeEventListener:i,addEventListener:n}},{}],33:[function(t,e){"use strict";function n(t){return"[object Function]"===Object.prototype.toString.call(t)}function i(t,e){return function(){t.apply(e,arguments)}}e.exports={bind:i,isFunction:n}},{}],34:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],35:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":31,"./lib/events":32,"./lib/fn":33,"./lib/url":34,dup:19}],36:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],37:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],38:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],39:[function(t,e){"use strict";function n(t){var e,n,i,r,o=[{min:0,max:180,chars:7},{min:181,max:620,chars:14},{min:621,max:960,chars:22}];for(r=o.length,t=t||window.innerWidth,n=0;r>n;n++)i=o[n],t>=i.min&&t<=i.max&&(e=i.chars);return e||60}function i(t,e){var n,i;return-1===t.indexOf("@")?t:(t=t.split("@"),n=t[0],i=t[1],n.length>e&&(n=n.slice(0,e)+"..."),i.length>e&&(i="..."+i.slice(-e)),n+"@"+i)}e.exports={truncateEmail:i,getMaxCharLength:n}},{}],40:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],41:[function(t,e){var n=t("./lib/dom"),i=t("./lib/url"),r=t("./lib/fn"),o=t("./lib/events"),s=t("./lib/string");e.exports={string:s,normalizeElement:n.normalizeElement,isBrowserHttps:i.isBrowserHttps,makeQueryString:i.makeQueryString,decodeQueryString:i.decodeQueryString,getParams:i.getParams,removeEventListener:o.removeEventListener,addEventListener:o.addEventListener,bind:r.bind,isFunction:r.isFunction}},{"./lib/dom":36,"./lib/events":37,"./lib/fn":38,"./lib/string":39,"./lib/url":40}],42:[function(t,e){"use strict";var n=t("framebus");n.events=t("./lib/events"),e.exports=n},{"./lib/events":43,framebus:44}],43:[function(t,e){"use strict";for(var n=["PAYMENT_METHOD_REQUEST","PAYMENT_METHOD_RECEIVED","PAYMENT_METHOD_GENERATED","PAYMENT_METHOD_CANCELLED","PAYMENT_METHOD_ERROR","CONFIGURATION_REQUEST","ERROR","WARNING"],i={},r=0;r<n.length;r++){var o=n[r];i[o]=o}e.exports=i},{}],44:[function(t,e,n){"use strict";!function(t,i){"function"==typeof define&&define.amd?define([],i):"object"==typeof n?e.exports=i():t.framebus=i()}(this,function(){function t(t,e,n){var r;return n=n||"*","string"!=typeof t?!1:"string"!=typeof n?!1:(r=i(t,e,n),c(h.top,r,n),!0)}function e(t,e,n){return n=n||"*",p(t,e,n)?!1:(d[n]=d[n]||{},d[n][t]=d[n][t]||[],d[n][t].push(e),!0)}function n(t,e,n){var i,r;if(n=n||"*",p(t,e,n))return!1;if(r=d[n]&&d[n][t],!r)return!1;for(i=0;i<r.length;i++)if(r[i]===e)return r.splice(i,1),!0;return!1}function i(t,e,n){var i={event:t};return"function"==typeof e?i.reply=l(e,n):i.data=e,JSON.stringify(i)}function r(t){var e;try{e=JSON.parse(t.data)}catch(n){return!1}return null==e.event?!1:(null!=e.reply&&(e.data=function(n){var r=i(e.reply,n,t.origin);t.source.postMessage(r,t.origin)}),e)}function o(t){h||(h=t,h.addEventListener?h.addEventListener("message",a,!1):h.attachEvent?h.attachEvent("onmessage",a):null===h.onmessage?h.onmessage=a:h=null)}function s(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=16*Math.random()|0,n="x"===t?e:3&e|8;return n.toString(16)})}function a(t){var e;"string"==typeof t.data&&(e=r(t),e&&(u("*",e.event,e.data,t.origin),u(t.origin,e.event,e.data,t.origin)))}function u(t,e,n,i){var r;if(d[t]&&d[t][e])for(r=0;r<d[t][e].length;r++)d[t][e][r](n,i)}function c(t,e,n){var i;for(t.postMessage(e,n),i=0;i<t.frames.length;i++)c(t.frames[i],e,n)}function l(t,i){function r(e,s){t(e,s),n(o,r,i)}var o=s();return e(o,r,i),o}function p(t,e,n){return"string"!=typeof t?!0:"function"!=typeof e?!0:"string"!=typeof n?!0:!1}var h,d={};return o(window),{publish:t,pub:t,trigger:t,emit:t,subscribe:e,sub:e,on:e,unsubscribe:n,unsub:n,off:n}})},{}],45:[function(t,e){"use strict";function n(t,e){u.emit(u.events.ERROR,{type:e,message:t})}function i(){var t=a.isIE();return t&&8===t.version}function r(t){if(null==t.apiClient)return n("settings.apiClient is required for coinbase",c),!1;if(!t.configuration.coinbaseEnabled)return n("Coinbase is not enabled for your merchant account",c),!1;var e=t.coinbase;return e&&(e.container||e.button)?e.container&&e.button?(n("options.coinbase.container and options.coinbase.button are mutually exclusive",c),!1):(i()&&n("Coinbase is not supported by your browser. Please consider upgrading","UNSUPPORTED_BROWSER"),!0):(n("Either options.coinbase.container or options.coinbase.button is required for coinbase integrations",c),!1)}function o(t){return r(t)?new s(t):void 0}var s=t("./lib/coinbase"),a=t("./lib/browser"),u=t("braintree-bus"),c="CONFIGURATION";e.exports={create:o}},{"./lib/browser":46,"./lib/coinbase":48,"braintree-bus":56}],46:[function(t,e){(function(t){"use strict";function n(){var t=null,e="";try{new ActiveXObject("")}catch(n){e=n.name}try{t=!!new ActiveXObject("htmlfile")}catch(n){t=!1}return t="ReferenceError"!==e&&t===!1?!1:!0,!t}function i(){var e={version:null};return/Trident/.test(t.navigator.userAgent)&&(e.version=11),/MSIE 10/.test(t.navigator.userAgent)&&(e.version=10),/MSIE 9/.test(t.navigator.userAgent)&&(e.version=9),/MSIE 8/.test(t.navigator.userAgent)&&(e.version=8),e
|
3 |
+
}function r(){return/MSIE|Trident/.test(t.navigator.userAgent)?i():null}e.exports={isMetroBrowser:n,isIE:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],47:[function(t,e){"use strict";function n(t,e,n){return t?(i.emit(i.events.ERROR,t.error),void n.sendAnalyticsEvents("coinbase.web.error")):(i.emit(i.events.PAYMENT_METHOD_GENERATED,e),void n.sendAnalyticsEvents("coinbase.web.success"))}var i=t("braintree-bus");e.exports={tokenize:n}},{"braintree-bus":56}],48:[function(t,e){(function(n){"use strict";function i(){}function r(t){return{clientId:t.configuration.coinbase.clientId,redirectUrl:t.configuration.coinbase.redirectUrl,scopes:t.configuration.coinbase.scopes||l.SCOPES,meta:{authorizations_merchant_account:t.configuration.coinbase.merchantAccount||""}}}function o(t){var e;this.buttonId=t.coinbase.button||l.BUTTON_ID,this.apiClient=t.apiClient,this.assetsUrl=t.configuration.assetsUrl,this._onOAuthSuccess=s.bind(this._onOAuthSuccess,this),this._handleButtonClick=s.bind(this._handleButtonClick,this),this.popupParams=r(t),this.redirectDoneInterval=null,e=document.body,n.braintreeCoinbaseRedirectCallback=this._onOAuthSuccess,t.coinbase.container?(e=s.normalizeElement(t.coinbase.container),this._insertFrame(e)):s.addEventListener(e,"click",this._handleButtonClick),this._sendAnalyticsEvents("coinbase.web.initialized")}var s=t("braintree-utilities"),a=t("./dom/composer"),u=t("./url-composer"),c=t("./callbacks"),l=t("./constants"),p=t("braintree-bus"),h=t("./detector");o.prototype._sendAnalyticsEvents=function(t){this.apiClient.sendAnalyticsEvents(t)},o.prototype._insertFrame=function(t){var e=a.createFrame({src:this.assetsUrl+"/coinbase/"+l.VERSION+"/coinbase-frame.html"});t.appendChild(e)},o.prototype._onOAuthSuccess=function(t){t.code&&(p.emit("coinbase:view:navigate","loading"),this._clearPollForRedirectDone(),this.apiClient.tokenizeCoinbase({code:t.code,query:u.getQueryString()},s.bind(function(t,e){c.tokenize.apply(null,[t,e,this.apiClient])},this)))},o.prototype._clearPollForRedirectDone=function(){this.redirectDoneInterval&&(clearInterval(this.redirectDoneInterval),this.redirectDoneInterval=null)},o.prototype._pollForRedirectDone=function(t){this.redirectDoneInterval=setInterval(s.bind(function(){var e;if(null==t||t.closed)return void this._clearPollForRedirectDone();try{e=s.decodeQueryString(t.location.search.replace(/^\?/,"")).code}catch(n){return}e&&(this._onOAuthSuccess({code:e}),t.close())},this),100)},o.prototype._openPopup=function(){var t;this._sendAnalyticsEvents("coinbase.web.start.popup"),t=a.createPopup(u.compose(this.popupParams)),n.popup=t,t.focus(),h.shouldPoll()&&(this._pollForRedirectDone(t),n.braintreeCoinbaseRedirectCallback=i)},o.prototype._handleButtonClick=function(t){for(var e=t.target||t.srcElement;;){if(null==e)return;if(e===t.currentTarget)return;if(e.id===this.buttonId)break;e=e.parentNode}t&&t.preventDefault?t.preventDefault():t.returnValue=!1,this._openPopup()},e.exports=o}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./callbacks":47,"./constants":49,"./detector":50,"./dom/composer":52,"./url-composer":55,"braintree-bus":56,"braintree-utilities":64}],49:[function(t,e){"use strict";e.exports={BASE_URL:"https://coinbase.com",ORIGIN_URL:"https://www.coinbase.com",FRAME_NAME:"braintree-coinbase-frame",POPUP_NAME:"coinbase",BUTTON_ID:"bt-coinbase-button",SCOPES:"send",VERSION:"0.0.3"}},{}],50:[function(t,e){"use strict";function n(){var t=r.isIE();return t&&t.version>9}function i(){return r.isIE()&&r.isMetroBrowser()}var r=t("./browser");e.exports={shouldPoll:n,shouldCloseFromParent:i}},{"./browser":46}],51:[function(t,e){"use strict";function n(t){var e=document.createElement("button");return t=t||{},e.id=t.id||"coinbase-button",e.style.backgroundColor=t.backgroundColor||"#EEE",e.style.color=t.color||"#4597C3",e.style.border=t.border||"0",e.style.borderRadius=t.borderRadius||"6px",e.style.padding=t.padding||"12px",e.innerHTML=t.innerHTML||"coinbase",e}e.exports={create:n}},{}],52:[function(t,e){"use strict";var n=t("./popup"),i=t("./button"),r=t("./frame");e.exports={createButton:i.create,createPopup:n.create,createFrame:r.create}},{"./button":51,"./frame":53,"./popup":54}],53:[function(t,e){"use strict";function n(t){var e=document.createElement("iframe");return e.src=t.src,e.id=i.FRAME_NAME,e.name=i.FRAME_NAME,e.allowTransparency=!0,e.height="70px",e.width="100%",e.frameBorder=0,e.style.padding=0,e.style.margin=0,e.style.border=0,e.style.outline="none",e}var i=t("../constants");e.exports={create:n}},{"../constants":49}],54:[function(t,e){(function(n){"use strict";function i(t){var e=[];for(var n in t)t.hasOwnProperty(n)&&e.push([n,t[n]].join("="));return e.join(",")}function r(){var t=850,e=600;return i({width:t,height:e,left:(screen.width-t)/2,top:(screen.height-e)/4})}function o(t){return n.open(t,s.POPUP_NAME,r())}var s=t("../constants");e.exports={create:o}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../constants":49}],55:[function(t,e){"use strict";function n(){return"version="+r.VERSION}function i(t){var e=r.BASE_URL+"/oauth/authorize?response_type=code",i=t.redirectUrl+"?"+n();if(e+="&redirect_uri="+encodeURIComponent(i),e+="&client_id="+t.clientId,t.scopes&&(e+="&scope="+encodeURIComponent(t.scopes)),t.meta)for(var o in t.meta)t.meta.hasOwnProperty(o)&&(e+="&meta["+encodeURIComponent(o)+"]="+encodeURIComponent(t.meta[o]));return e}var r=t("./constants");e.exports={compose:i,getQueryString:n}},{"./constants":49}],56:[function(t,e,n){arguments[4][42][0].apply(n,arguments)},{"./lib/events":57,dup:42,framebus:58}],57:[function(t,e,n){arguments[4][43][0].apply(n,arguments)},{dup:43}],58:[function(t,e,n){arguments[4][44][0].apply(n,arguments)},{dup:44}],59:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],60:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],61:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],62:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],63:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],64:[function(t,e,n){arguments[4][41][0].apply(n,arguments)},{"./lib/dom":59,"./lib/events":60,"./lib/fn":61,"./lib/string":62,"./lib/url":63,dup:41}],65:[function(t,e){(function(n){"use strict";function i(t,e){return t.status>=400?[t,null]:[null,e(t)]}function r(t){var e;this.attrs={},t.hasOwnProperty("sharedCustomerIdentifier")&&(this.attrs.sharedCustomerIdentifier=t.sharedCustomerIdentifier),e=c(t.clientToken),this.driver=t.driver||l,this.authUrl=e.authUrl,this.analyticsUrl=e.analytics?e.analytics.url:void 0,this.clientApiUrl=e.clientApiUrl,this.customerId=t.customerId,this.challenges=e.challenges,this.integration=t.integration||"";var n=u.create(this,{container:t.container,clientToken:e});this.verify3DS=a.bind(n.verify,n),this.attrs.authorizationFingerprint=e.authorizationFingerprint,this.attrs.sharedCustomerIdentifierType=t.sharedCustomerIdentifierType,e.merchantAccountId&&(this.attrs.merchantAccountId=e.merchantAccountId),this.timeoutWatchers=[],this.requestTimeout=t.hasOwnProperty("timeout")?t.timeout:6e4}function o(){}function s(t,e){var n,i={};for(n in t)t.hasOwnProperty(n)&&(i[n]=t[n]);for(n in e)e.hasOwnProperty(n)&&(i[n]=e[n]);return i}var a=t("braintree-utilities"),u=t("braintree-3ds"),c=t("./parse-client-token"),l=t("./jsonp-driver"),p=t("./util"),h=t("./sepa-mandate"),d=t("./sepa-bank-account"),f=t("./credit-card"),m=t("./coinbase-account"),y=t("./root-data"),g=t("./normalize-api-fields").normalizeCreditCardFields;r.prototype.requestWithTimeout=function(t,e,n,r,s){s=s||o;var a,u,c=this;y.get(function(o){u="braintree/web/"+o.sdkVersion,e.braintreeLibraryVersion=u,e.hasOwnProperty("analytics")&&e.hasOwnProperty("_meta")&&(e._meta.sdkVersion=u,e._meta.merchantAppId=o.merchantAppId),a=r(t,e,function(t,e){if(c.timeoutWatchers[e]){clearTimeout(c.timeoutWatchers[e]);var r=i(t,function(t){return n(t)});s.apply(null,r)}}),c.requestTimeout>0?this.timeoutWatchers[a]=setTimeout(function(){c.timeoutWatchers[a]=null,s.apply(null,[{errors:"Unknown error"},null])},c.requestTimeout):s.apply(null,[{errors:"Unknown error"},null])},this)},r.prototype.post=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.post,i)},r.prototype.get=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.get,i)},r.prototype.put=function(t,e,n,i){this.requestWithTimeout(t,e,n,this.driver.put,i)},r.prototype.getCreditCards=function(t){this.get(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods"]),this.attrs,function(t){var e=0,n=t.paymentMethods.length,i=[];for(e;n>e;e++)i.push(new f(t.paymentMethods[e]));return i},t)},r.prototype.tokenizeCoinbase=function(t,e){t.options={validate:!1},this.addCoinbase(t,function(t,n){t?e(t,null):n&&n.nonce?e(t,n):e("Unable to tokenize coinbase account.",null)})},r.prototype.tokenizeCard=function(t,e){t.options={validate:!1},this.addCreditCard(t,function(t,n){n&&n.nonce?e(t,n.nonce,{type:n.type}):e("Unable to tokenize card.",null)})},r.prototype.lookup3DS=function(t,e){var n=p.joinUrlFragments([this.clientApiUrl,"v1/payment_methods",t.nonce,"three_d_secure/lookup"]),i=s(this.attrs,{amount:t.amount});this.post(n,i,function(t){return t},e)},r.prototype.addSEPAMandate=function(t,e){var n=s(this.attrs,{sepaMandate:t});this.post(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates.json"]),n,function(t){return new h(t.sepaMandates[0])},e)},r.prototype.acceptSEPAMandate=function(t,e){this.put(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates",t,"accept"]),this.attrs,function(t){return new d(t.sepaBankAccounts[0])},e)},r.prototype.getSEPAMandate=function(t,e){var n;n=t.paymentMethodToken?s(this.attrs,{paymentMethodToken:t.paymentMethodToken}):this.attrs,this.get(p.joinUrlFragments([this.clientApiUrl,"v1","sepa_mandates",t.mandateReferenceNumber||""]),n,function(t){return new h(t.sepaMandates[0])},e)},r.prototype.addCoinbase=function(t,e){var n;delete t.share,n=s(this.attrs,{coinbaseAccount:t,_meta:{integration:this.integration||"custom",source:"coinbase"}}),this.post(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/coinbase_accounts"]),n,function(t){return new m(t.coinbaseAccounts[0])},e)},r.prototype.addCreditCard=function(t,e){var n,i=t.share;delete t.share;var r=g(t);n=s(this.attrs,{share:i,creditCard:r,_meta:{integration:this.integration||"custom",source:"form"}}),this.post(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/credit_cards"]),n,function(t){return new f(t.creditCards[0])},e)},r.prototype.unlockCreditCard=function(t,e,n){var i=s(this.attrs,{challengeResponses:e});this.put(p.joinUrlFragments([this.clientApiUrl,"v1","payment_methods/",t.nonce]),i,function(t){return new f(t.paymentMethods[0])},n)},r.prototype.sendAnalyticsEvents=function(t,e){var i,r=this.analyticsUrl,o=[];if(t=p.isArray(t)?t:[t],!r)return void(e&&e.apply(null,[null,{}]));for(var a in t)t.hasOwnProperty(a)&&o.push({kind:t[a]});i=s(this.attrs,{analytics:o,_meta:{platform:"web",platformVersion:n.navigator.userAgent,integrationType:this.integration}}),this.post(r,i,function(t){return t},e)},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./coinbase-account":66,"./credit-card":67,"./jsonp-driver":68,"./normalize-api-fields":70,"./parse-client-token":71,"./root-data":73,"./sepa-bank-account":74,"./sepa-mandate":75,"./util":76,"braintree-3ds":85,"braintree-utilities":104}],66:[function(t,e,n){arguments[4][3][0].apply(n,arguments)},{dup:3}],67:[function(t,e,n){arguments[4][4][0].apply(n,arguments)},{dup:4}],68:[function(t,e,n){arguments[4][5][0].apply(n,arguments)},{"./jsonp":69,dup:5}],69:[function(t,e,n){arguments[4][6][0].apply(n,arguments)},{"./util":76,dup:6}],70:[function(t,e,n){arguments[4][7][0].apply(n,arguments)},{dup:7}],71:[function(t,e,n){arguments[4][8][0].apply(n,arguments)},{"./polyfill":72,dup:8}],72:[function(t,e,n){arguments[4][9][0].apply(n,arguments)},{dup:9}],73:[function(t,e,n){arguments[4][10][0].apply(n,arguments)},{"braintree-rpc":93,dup:10}],74:[function(t,e,n){arguments[4][11][0].apply(n,arguments)},{dup:11}],75:[function(t,e,n){arguments[4][12][0].apply(n,arguments)},{dup:12}],76:[function(t,e,n){arguments[4][13][0].apply(n,arguments)},{dup:13}],77:[function(t,e,n){arguments[4][14][0].apply(n,arguments)},{"./lib/client":65,"./lib/jsonp":69,"./lib/jsonp-driver":68,"./lib/parse-client-token":71,"./lib/util":76,dup:14}],78:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],79:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],80:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],81:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],82:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":78,"./lib/events":79,"./lib/fn":80,"./lib/url":81,dup:19}],83:[function(t,e){"use strict";function n(t,e){var n=window.getComputedStyle?getComputedStyle(t):t.currentStyle;return n[e]}function i(){return{html:{height:o.style.height||"",overflow:n(o,"overflow"),position:n(o,"position")},body:{height:s.style.height||"",overflow:n(s,"overflow")}}}function r(t,e){this.assetsUrl=t,this.container=e||document.body,this.iframe=null,o=document.documentElement,s=document.body,this.merchantPageDefaultStyles=i()}var o,s,a=t("braintree-utilities"),u=t("../shared/receiver"),c="1.1.0";r.prototype.get=function(t,e){var n=this,i=this.constructAuthorizationURL(t);this.container&&a.isFunction(this.container)?this.container(i+"&no_style=1"):this.insertIframe(i),new u(function(t){a.isFunction(n.container)||n.removeIframe(),e(t)})},r.prototype.removeIframe=function(){this.container&&this.container.nodeType&&1===this.container.nodeType?this.container.removeChild(this.iframe):this.container&&window.jQuery&&this.container instanceof jQuery?$(this.iframe,this.container).remove():"string"==typeof this.container&&document.getElementById(this.container).removeChild(this.iframe),this.unlockMerchantWindowSize()},r.prototype.insertIframe=function(t){var e=document.createElement("iframe");if(e.src=t,this.applyStyles(e),this.lockMerchantWindowSize(),this.container&&this.container.nodeType&&1===this.container.nodeType)this.container.appendChild(e);else if(this.container&&window.jQuery&&this.container instanceof jQuery&&0!==this.container.length)this.container.append(e);else{if("string"!=typeof this.container||!document.getElementById(this.container))throw new Error("Unable to find valid container for iframe.");document.getElementById(this.container).appendChild(e)}this.iframe=e},r.prototype.applyStyles=function(t){t.style.position="fixed",t.style.top="0",t.style.left="0",t.style.height="100%",t.style.width="100%",t.setAttribute("frameborder","0"),t.setAttribute("allowTransparency","true"),t.style.border="0",t.style.zIndex="99999"},r.prototype.lockMerchantWindowSize=function(){o.style.overflow="hidden",s.style.overflow="hidden",s.style.height="100%"},r.prototype.unlockMerchantWindowSize=function(){var t=this.merchantPageDefaultStyles;s.style.height=t.body.height,s.style.overflow=t.body.overflow,o.style.overflow=t.html.overflow},r.prototype.constructAuthorizationURL=function(t){var e,n=window.location.href;return n.indexOf("#")>-1&&(n=n.split("#")[0]),e=a.makeQueryString({acsUrl:t.acsUrl,pareq:t.pareq,termUrl:t.termUrl+"&three_d_secure_version="+c,md:t.md,parentUrl:n}),this.assetsUrl+"/3ds/"+c+"/html/style_frame?"+e},e.exports=r},{"../shared/receiver":87,"braintree-utilities":82}],84:[function(t,e){"use strict";function n(t,e){e=e||{},this.clientToken=e.clientToken,this.container=e.container,this.api=t,this.nonce=null}var i=t("braintree-utilities"),r=t("./authorization_service");n.prototype.verify=function(t,e){if(!i.isFunction(e))throw this.api.sendAnalyticsEvents("3ds.web.no_callback"),new Error("No suitable callback argument was given");var n={nonce:"",amount:t.amount},r=t.creditCard;if("string"==typeof r)n.nonce=r,this.api.sendAnalyticsEvents("3ds.web.verify.nonce"),this.startVerification(n,e);else{var o=this,s=function(t,i){return t?e(t):(n.nonce=i,void o.startVerification(n,e))};this.api.sendAnalyticsEvents("3ds.web.verify.credit_card"),this.api.tokenizeCard(r,s)}},n.prototype.startVerification=function(t,e){this.api.lookup3DS(t,i.bind(this.handleLookupResponse(e),this))},n.prototype.handleLookupResponse=function(t){var e=this;return function(n,o){var s;n?t(n.error):o.lookup&&o.lookup.acsUrl&&o.lookup.acsUrl.length>0?(e.nonce=o.paymentMethod.nonce,s=new r(this.clientToken.assetsUrl,this.container),s.get(o.lookup,i.bind(this.handleAuthenticationResponse(t),this))):(e.nonce=o.paymentMethod.nonce,t(null,{nonce:e.nonce,verificationDetails:o.threeDSecureInfo}))}},n.prototype.handleAuthenticationResponse=function(t){return function(e){var n,r=i.decodeQueryString(e);r.user_closed||(n=JSON.parse(r.auth_response),n.success?t(null,{nonce:n.paymentMethod.nonce,verificationDetails:n.threeDSecureInfo}):n.threeDSecureInfo&&n.threeDSecureInfo.liabilityShiftPossible?t(null,{nonce:this.nonce,verificationDetails:n.threeDSecureInfo}):t(n.error))}},e.exports=n},{"./authorization_service":83,"braintree-utilities":82}],85:[function(t,e,n){arguments[4][22][0].apply(n,arguments)},{"./client":84,"./vendor/json2":86,dup:22}],86:[function(t,e,n){arguments[4][23][0].apply(n,arguments)},{dup:23}],87:[function(t,e){"use strict";function n(t){this.postMessageReceiver(t),this.hashChangeReceiver(t)}var i=t("braintree-utilities");n.prototype.postMessageReceiver=function(t){var e=this;this.wrappedCallback=function(n){t(n.data),e.stopListening()},i.addEventListener(window,"message",this.wrappedCallback)},n.prototype.hashChangeReceiver=function(t){var e,n=window.location.hash,i=this;this.poll=setInterval(function(){e=window.location.hash,e.length>0&&e!==n&&(i.stopListening(),e=e.substring(1,e.length),t(e),window.location.hash=n.length>0?n:"")},10)},n.prototype.stopListening=function(){clearTimeout(this.poll),i.removeEventListener(window,"message",this.wrappedCallback)},e.exports=n},{"braintree-utilities":82}],88:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":98,dup:25}],89:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":98,dup:26}],90:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],91:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":98,dup:28}],92:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":98,dup:29}],93:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":88,"./lib/pubsub-client":89,"./lib/pubsub-server":90,"./lib/rpc-client":91,"./lib/rpc-server":92,dup:30}],94:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],95:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],96:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],97:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],98:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":94,"./lib/events":95,"./lib/fn":96,"./lib/url":97,dup:19}],99:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],100:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],101:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],102:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],103:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],104:[function(t,e,n){arguments[4][41][0].apply(n,arguments)},{"./lib/dom":99,"./lib/events":100,"./lib/fn":101,"./lib/string":102,"./lib/url":103,dup:41}],105:[function(t,e,n){arguments[4][42][0].apply(n,arguments)},{"./lib/events":106,dup:42,framebus:107}],106:[function(t,e,n){arguments[4][43][0].apply(n,arguments)},{dup:43}],107:[function(t,e,n){arguments[4][44][0].apply(n,arguments)},{dup:44}],108:[function(t,e,n){arguments[4][2][0].apply(n,arguments)},{"./coinbase-account":109,"./credit-card":110,"./jsonp-driver":111,"./normalize-api-fields":113,"./parse-client-token":114,"./root-data":116,"./sepa-bank-account":117,"./sepa-mandate":118,"./util":119,"braintree-3ds":128,"braintree-utilities":147,dup:2}],109:[function(t,e,n){arguments[4][3][0].apply(n,arguments)},{dup:3}],110:[function(t,e,n){arguments[4][4][0].apply(n,arguments)},{dup:4}],111:[function(t,e,n){arguments[4][5][0].apply(n,arguments)},{"./jsonp":112,dup:5}],112:[function(t,e,n){arguments[4][6][0].apply(n,arguments)},{"./util":119,dup:6}],113:[function(t,e,n){arguments[4][7][0].apply(n,arguments)},{dup:7}],114:[function(t,e,n){arguments[4][8][0].apply(n,arguments)},{"./polyfill":115,dup:8}],115:[function(t,e,n){arguments[4][9][0].apply(n,arguments)},{dup:9}],116:[function(t,e,n){arguments[4][10][0].apply(n,arguments)},{"braintree-rpc":136,dup:10}],117:[function(t,e,n){arguments[4][11][0].apply(n,arguments)},{dup:11}],118:[function(t,e,n){arguments[4][12][0].apply(n,arguments)},{dup:12}],119:[function(t,e,n){arguments[4][13][0].apply(n,arguments)},{dup:13}],120:[function(t,e,n){arguments[4][14][0].apply(n,arguments)},{"./lib/client":108,"./lib/jsonp":112,"./lib/jsonp-driver":111,"./lib/parse-client-token":114,"./lib/util":119,dup:14}],121:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],122:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],123:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],124:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],125:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":121,"./lib/events":122,"./lib/fn":123,"./lib/url":124,dup:19}],126:[function(t,e,n){arguments[4][20][0].apply(n,arguments)},{"../shared/receiver":130,"braintree-utilities":125,dup:20}],127:[function(t,e,n){arguments[4][21][0].apply(n,arguments)},{"./authorization_service":126,"braintree-utilities":125,dup:21}],128:[function(t,e,n){arguments[4][22][0].apply(n,arguments)},{"./client":127,"./vendor/json2":129,dup:22}],129:[function(t,e,n){arguments[4][23][0].apply(n,arguments)},{dup:23}],130:[function(t,e,n){arguments[4][24][0].apply(n,arguments)},{"braintree-utilities":125,dup:24}],131:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":141,dup:25}],132:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":141,dup:26}],133:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],134:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":141,dup:28}],135:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":141,dup:29}],136:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":131,"./lib/pubsub-client":132,"./lib/pubsub-server":133,"./lib/rpc-client":134,"./lib/rpc-server":135,dup:30}],137:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],138:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],139:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],140:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],141:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":137,"./lib/events":138,"./lib/fn":139,"./lib/url":140,dup:19}],142:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],143:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],144:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],145:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],146:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],147:[function(t,e,n){arguments[4][41][0].apply(n,arguments)},{"./lib/dom":142,"./lib/events":143,"./lib/fn":144,"./lib/string":145,"./lib/url":146,dup:41}],148:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":158,dup:25}],149:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":158,dup:26}],150:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],151:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":158,dup:28}],152:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":158,dup:29}],153:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":148,"./lib/pubsub-client":149,"./lib/pubsub-server":150,"./lib/rpc-client":151,"./lib/rpc-server":152,dup:30}],154:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],155:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],156:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],157:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],158:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":154,"./lib/events":155,"./lib/fn":156,"./lib/url":157,dup:19}],159:[function(t,e){"use strict";var n,i=Array.prototype.indexOf;n=i?function(t,e){return t.indexOf(e)}:function(t,e){for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n;return-1},e.exports={indexOf:n}},{}],160:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],161:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],162:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],163:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],164:[function(t,e){"use strict";function n(){return"https:"===window.location.protocol}function i(t){switch(t){case null:case void 0:return"";case!0:return"1";case!1:return"0";default:return encodeURIComponent(t)}}function r(t,e){var n,o,s=[];for(o in t)if(t.hasOwnProperty(o)){var a=t[o];n=e?e+"["+o+"]":o,"object"==typeof a?s.push(r(a,n)):void 0!==a&&null!==a&&s.push(i(n)+"="+i(a))}return s.join("&")}function o(t){for(var e={},n=t.split("&"),i=0;i<n.length;i++){var r=n[i].split("="),o=r[0],s=decodeURIComponent(r[1]);e[o]=s}return e}function s(t){var e=t.split("?");return 2!==e.length?{}:o(e[1])}function a(t){if(t=t.toLowerCase(),!/^http/.test(t))return!1;c.href=t;var e=c.hostname.split("."),n=e.slice(-2).join(".");return-1===u.indexOf(l,n)?!1:!0}var u=t("./array"),c=document.createElement("a"),l=["paypal.com","braintreepayments.com","braintreegateway.com","localhost"];e.exports={isBrowserHttps:n,makeQueryString:r,decodeQueryString:o,getParams:s,isWhitelistedDomain:a}},{"./array":159}],165:[function(t,e){var n=t("./lib/dom"),i=t("./lib/url"),r=t("./lib/fn"),o=t("./lib/events"),s=t("./lib/string"),a=t("./lib/array");e.exports={string:s,array:a,normalizeElement:n.normalizeElement,isBrowserHttps:i.isBrowserHttps,makeQueryString:i.makeQueryString,decodeQueryString:i.decodeQueryString,getParams:i.getParams,isWhitelistedDomain:i.isWhitelistedDomain,removeEventListener:o.removeEventListener,addEventListener:o.addEventListener,bind:r.bind,isFunction:r.isFunction}},{"./lib/array":159,"./lib/dom":160,"./lib/events":161,"./lib/fn":162,"./lib/string":163,"./lib/url":164}],166:[function(t,e){function n(t){var e=window.getComputedStyle?getComputedStyle(t):t.currentStyle;return{overflow:e.overflow||"",height:t.style.height||""}}function i(){return{html:{node:document.documentElement,styles:n(document.documentElement)},body:{node:document.body,styles:n(document.body)}}}function r(t,e){if(!t)throw new Error('Parameter "clientToken" cannot be null');e=e||{},this._clientToken=o.parseClientToken(t),this._clientOptions=e,this.container=e.container,this.merchantPageDefaultStyles=null,this.paymentMethodNonceInputField=e.paymentMethodNonceInputField,this.frame=null,this.popup=null,this.insertFrameFunction=e.insertFrame,this.onSuccess=e.onSuccess,this.onCancelled=e.onCancelled,this.onUnsupported=e.onUnsupported,this.loggedInView=null,this.loggedOutView=null,this.insertUI=!0}var o=t("braintree-api"),s=t("braintree-rpc"),a=t("braintree-utilities"),u=t("./logged-in-view"),c=t("./logged-out-view"),l=t("./overlay-view"),p=t("../shared/util/browser"),h=t("../shared/util/dom"),d=t("../shared/constants"),f=t("../shared/util/util"),m=t("../shared/get-locale");r.prototype.getViewerUrl=function(){var t=this._clientToken.paypal.assetsUrl;return t+"/pwpp/"+d.VERSION+"/html/braintree-frame.html"},r.prototype.getProxyUrl=function(){var t=this._clientToken.paypal.assetsUrl;return t+"/pwpp/"+d.VERSION+"/html/proxy-frame.html"},r.prototype.initialize=function(){if(!this._clientToken.paypalEnabled)return void("function"==typeof this.onUnsupported&&this.onUnsupported(new Error("PayPal is not enabled")));if(!this._isBrowserSecure())return void("function"==typeof this.onUnsupported&&this.onUnsupported(new Error("unsupported protocol detected")));if(this._isAriesCapable()){if(!this._isAriesSupportedCurrency())return void("function"==typeof this.onUnsupported&&this.onUnsupported(new Error("This PayPal integration does not support this currency")));if(!this._isAriesSupportedCountries())return void("function"==typeof this.onUnsupported&&this.onUnsupported(new Error("This PayPal integration does not support this locale")))}return this._isMisconfiguredUnvettedMerchant()?void("function"==typeof this.onUnsupported&&this.onUnsupported(new Error("Unvetted merchant client token does not include a payee email"))):(this._overrideClientTokenProperties(),p.isProxyFrameRequired()&&this._insertProxyFrame(),this._setupDomElements(),this._setupPaymentMethodNonceInputField(),this._setupViews(),void this._createRpcServer())},r.prototype._isSupportedOption=function(t,e){for(var n=e.length,i=!1,r=0;n>r;r++)t.toLowerCase()===e[r].toLowerCase()&&(i=!0);return i},r.prototype._isAriesSupportedCurrency=function(){return this._isSupportedOption(this._clientOptions.currency,d.ARIES_SUPPORTED_CURRENCIES)},r.prototype._isAriesSupportedCountries=function(){return this._isSupportedOption(m(this._clientOptions.locale).split("_")[1],d.ARIES_SUPPORTED_COUNTRIES)},r.prototype._isMisconfiguredUnvettedMerchant=function(){return this._clientToken.paypal.unvettedMerchant&&(!this._isAriesCapable()||!this._clientToken.paypal.payeeEmail)},r.prototype._isBrowserSecure=function(){return a.isBrowserHttps()||p.isPopupSupported()||this._clientToken.paypal.allowHttp},r.prototype._overrideClientTokenProperties=function(){this._clientOptions.displayName&&(this._clientToken.paypal.displayName=this._clientOptions.displayName)},r.prototype._setupDomElements=function(){this.insertUI&&(this.container=a.normalizeElement(this.container))},r.prototype._setupPaymentMethodNonceInputField=function(){if(this.insertUI){var t=this.paymentMethodNonceInputField;a.isFunction(t)||(t=void 0!==t?a.normalizeElement(t):this._createPaymentMethodNonceInputField(),this.paymentMethodNonceInputField=t)}},r.prototype._setupViews=function(){var t=this._clientToken.paypal.assetsUrl;this.insertUI&&(this.loggedInView=new u({container:this.container,assetsUrl:t}),this.loggedOutView=new c({assetsUrl:t,container:this.container,isCheckout:this._isAriesCapable(),locale:this._clientOptions.locale,merchantId:"merchantId"}),a.addEventListener(this.loggedOutView.container,"click",a.bind(this._handleContainerClick,this)),a.addEventListener(this.loggedInView.logoutNode,"click",a.bind(this._handleLogout,this)))},r.prototype._createRpcServer=function(){var t=new s.MessageBus(window),e=new s.RPCServer(t,window);e.define("getClientToken",a.bind(this._handleGetClientToken,this)),e.define("getClientOptions",a.bind(this._handleGetClientOptions,this)),e.define("closePayPalModal",a.bind(this._handleCloseMessage,this)),e.define("receivePayPalData",a.bind(this._handleSuccessfulAuthentication,this))},r.prototype._createPaymentMethodNonceInputField=function(){var t=document.createElement("input");return t.name="payment_method_nonce",t.type="hidden",this.container.appendChild(t)},r.prototype._createFrame=function(){var t,e=document.createElement("iframe");return this._isAriesCapable()?(t=d.ARIES_FRAME_NAME,e.style.background="#FFFFFF"):t=d.FRAME_NAME,e.src=this.getViewerUrl(),e.id=t,e.name=t,e.allowTransparency=!0,e.height="100%",e.width="100%",e.frameBorder=0,e.style.position=p.isMobile()?"absolute":"fixed",e.style.top=0,e.style.left=0,e.style.bottom=0,e.style.zIndex=20001,e.style.padding=0,e.style.margin=0,e.style.border=0,e.style.outline="none",e
|
4 |
+
},r.prototype._removeFrame=function(t){t=t||document.body,this.frame&&t.contains(this.frame)&&(t.removeChild(this.frame),this._unlockMerchantWindowSize())},r.prototype._insertFrame=function(){this.insertFrameFunction?this.insertFrameFunction(this.getViewerUrl()):(this.frame=this._createFrame(),document.body.appendChild(this.frame)),this._lockMerchantWindowSize()},r.prototype._handleContainerClick=function(t){function e(t){return t.className.match(/paypal-button(?!-widget)/)||"braintree-paypal-button"===t.id}var n=t.target||t.srcElement;(e(n)||e(n.parentNode))&&(t.preventDefault?t.preventDefault():t.returnValue=!1,this._open())},r.prototype._setMerchantPageDefaultStyles=function(){this.merchantPageDefaultStyles=i()},r.prototype._open=function(){this._isAriesCapable()&&this._addCorrelationIdToClientToken(),p.isPopupSupported()?this._openPopup():this._openModal()},r.prototype._close=function(){p.isPopupSupported()?this._closePopup():this._closeModal()},r.prototype._openModal=function(){this._removeFrame(),this._insertFrame()},r.prototype._isAriesCapable=function(){return!(!this._clientOptions.singleUse||!this._clientOptions.amount||!this._clientOptions.currency||this._clientOptions.demo)},r.prototype._openPopup=function(){var t,e,n,i=[],r=window.outerWidth||document.documentElement.clientWidth,o=window.outerHeight||document.documentElement.clientHeight,s="undefined"==typeof window.screenY?window.screenTop:window.screenY,a="undefined"==typeof window.screenX?window.screenLeft:window.screenX;this._isAriesCapable()?(t=d.ARIES_POPUP_NAME,n=d.ARIES_POPUP_HEIGHT,e=d.ARIES_POPUP_WIDTH):(t=d.POPUP_NAME,n=d.POPUP_HEIGHT,e=d.POPUP_WIDTH);var u=(r-e)/2+a,c=(o-n)/2+s;return i.push("height="+n),i.push("width="+e),i.push("top="+c),i.push("left="+u),i.push(d.POPUP_OPTIONS),this.popup=window.open(this.getViewerUrl(),t,i.join(",")),p.isOverlaySupported()&&(this.overlayView=new l(this.popup,this._clientToken.paypal.assetsUrl),this.overlayView.render()),this.popup.focus(),this.popup},r.prototype._addCorrelationIdToClientToken=function(){this._clientToken.correlationId=f.generateUid()},r.prototype._createProxyFrame=function(){var t=document.createElement("iframe");return t.src=this.getProxyUrl(),t.id=d.BRIDGE_FRAME_NAME,t.name=d.BRIDGE_FRAME_NAME,t.allowTransparency=!0,t.height=0,t.width=0,t.frameBorder=0,t.style.position="static",t.style.padding=0,t.style.margin=0,t.style.border=0,t.style.outline="none",t},r.prototype._insertProxyFrame=function(){this.proxyFrame=this._createProxyFrame(),document.body.appendChild(this.proxyFrame)},r.prototype._closeModal=function(){this._removeFrame()},r.prototype._closePopup=function(){this.popup&&(this.popup.close(),this.popup=null),this.overlayView&&p.isOverlaySupported()&&this.overlayView.remove()},r.prototype._clientTokenData=function(){return{analyticsUrl:this._clientToken.analytics?this._clientToken.analytics.url:void 0,authorizationFingerprint:this._clientToken.authorizationFingerprint,authUrl:this._clientToken.authUrl,clientApiUrl:this._clientToken.clientApiUrl,displayName:this._clientToken.paypal.displayName,paypalBaseUrl:this._clientToken.paypal.assetsUrl,paypalClientId:this._clientToken.paypal.clientId,paypalPrivacyUrl:this._clientToken.paypal.privacyUrl,paypalUserAgreementUrl:this._clientToken.paypal.userAgreementUrl,unvettedMerchant:this._clientToken.paypal.unvettedMerchant,payeeEmail:this._clientToken.paypal.payeeEmail,correlationId:this._clientToken.correlationId,offline:this._clientOptions.offline||this._clientToken.paypal.environmentNoNetwork}},r.prototype._handleGetClientToken=function(t){t(this._clientTokenData())},r.prototype._clientOptionsData=function(){return{demo:this._clientOptions.demo||!1,locale:this._clientOptions.locale||"en_us",onetime:this._clientOptions.singleUse||!1,integration:this._clientOptions.integration||"paypal",enableShippingAddress:this._clientOptions.enableShippingAddress||!1,enableAries:this._isAriesCapable(),amount:this._clientOptions.amount||null,currency:this._clientOptions.currency||null,shippingAddressOverride:this._clientOptions.shippingAddressOverride||null}},r.prototype._handleGetClientOptions=function(t){t(this._clientOptionsData())},r.prototype._handleSuccessfulAuthentication=function(t){this._close(),t.type=d.NONCE_TYPE,a.isFunction(this.paymentMethodNonceInputField)?this.paymentMethodNonceInputField(t.nonce):(this._showLoggedInContent(t.details.email),this._setNonceInputValue(t.nonce)),a.isFunction(this.onSuccess)&&this.onSuccess(t)},r.prototype._lockMerchantWindowSize=function(){this._setMerchantPageDefaultStyles(),document.documentElement.style.height="100%",document.documentElement.style.overflow="hidden",document.body.style.height="100%",document.body.style.overflow="hidden"},r.prototype._unlockMerchantWindowSize=function(){this.merchantPageDefaultStyles&&(document.documentElement.style.height=this.merchantPageDefaultStyles.html.styles.height,document.documentElement.style.overflow=this.merchantPageDefaultStyles.html.styles.overflow,document.body.style.height=this.merchantPageDefaultStyles.body.styles.height,document.body.style.overflow=this.merchantPageDefaultStyles.body.styles.overflow)},r.prototype._handleCloseMessage=function(){this._removeFrame()},r.prototype._showLoggedInContent=function(t){this.loggedOutView.hide(),h.setTextContent(this.loggedInView.emailNode,t),this.loggedInView.show()},r.prototype._handleLogout=function(t){t.preventDefault?t.preventDefault():t.returnValue=!1,this.loggedInView.hide(),this.loggedOutView.show(),this._setNonceInputValue(""),a.isFunction(this.onCancelled)&&this.onCancelled()},r.prototype._setNonceInputValue=function(t){this.paymentMethodNonceInputField.value=t},e.exports=r},{"../shared/constants":170,"../shared/get-locale":172,"../shared/util/browser":177,"../shared/util/dom":178,"../shared/util/util":179,"./logged-in-view":167,"./logged-out-view":168,"./overlay-view":169,"braintree-api":120,"braintree-rpc":153,"braintree-utilities":165}],167:[function(t,e){function n(t){this.options=t,this.container=this.createViewContainer(),this.createPayPalName(),this.emailNode=this.createEmailNode(),this.logoutNode=this.createLogoutNode()}var i=t("../shared/constants");n.prototype.createViewContainer=function(){var t=document.createElement("div");t.id="braintree-paypal-loggedin";var e=["display: none","max-width: 500px","overflow: hidden","padding: 16px","background-image: url("+this.options.assetsUrl+"/pwpp/"+i.VERSION+"/images/paypal-small.png)","background-image: url("+this.options.assetsUrl+"/pwpp/"+i.VERSION+"/images/paypal-small.svg), none","background-position: 20px 50%","background-repeat: no-repeat","background-size: 13px 15px","border-top: 1px solid #d1d4d6","border-bottom: 1px solid #d1d4d6"].join(";");return t.style.cssText=e,this.options.container.appendChild(t),t},n.prototype.createPayPalName=function(){var t=document.createElement("span");t.id="bt-pp-name",t.innerHTML="PayPal";var e=["color: #283036","font-size: 13px","font-weight: 800",'font-family: "Helvetica Neue", Helvetica, Arial, sans-serif',"margin-left: 36px","-webkit-font-smoothing: antialiased","-moz-font-smoothing: antialiased","-ms-font-smoothing: antialiased","font-smoothing: antialiased"].join(";");return t.style.cssText=e,this.container.appendChild(t)},n.prototype.createEmailNode=function(){var t=document.createElement("span");t.id="bt-pp-email";var e=["color: #6e787f","font-size: 13px",'font-family: "Helvetica Neue", Helvetica, Arial, sans-serif',"margin-left: 5px","-webkit-font-smoothing: antialiased","-moz-font-smoothing: antialiased","-ms-font-smoothing: antialiased","font-smoothing: antialiased"].join(";");return t.style.cssText=e,this.container.appendChild(t)},n.prototype.createLogoutNode=function(){var t=document.createElement("button");t.id="bt-pp-cancel",t.innerHTML="Cancel";var e=["color: #3d95ce","font-size: 11px",'font-family: "Helvetica Neue", Helvetica, Arial, sans-serif',"line-height: 20px","margin: 0 0 0 25px","padding: 0","background-color: transparent","border: 0","cursor: pointer","text-decoration: underline","float: right","-webkit-font-smoothing: antialiased","-moz-font-smoothing: antialiased","-ms-font-smoothing: antialiased","font-smoothing: antialiased"].join(";");return t.style.cssText=e,this.container.appendChild(t)},n.prototype.show=function(){this.container.style.display="block"},n.prototype.hide=function(){this.container.style.display="none"},e.exports=n},{"../shared/constants":170}],168:[function(t,e){function n(t){this.options=t,this.assetsUrl=this.options.assetsUrl,this.container=this.createViewContainer(),this.options.isCheckout?this.createCheckoutWithPayPalButton():this.createPayWithPayPalButton()}var i=(t("braintree-utilities"),t("../shared/constants")),r=t("../shared/get-locale");n.prototype.createViewContainer=function(){var t=document.createElement("div");return t.id="braintree-paypal-loggedout",this.options.container.appendChild(t),t},n.prototype.createPayWithPayPalButton=function(){var t=document.createElement("a");t.id="braintree-paypal-button",t.href="#";var e=["display: block","width: 115px","height: 44px","overflow: hidden"].join(";");t.style.cssText=e;var n=new Image;n.src=this.assetsUrl+"/pwpp/"+i.VERSION+"/images/pay-with-paypal.png",n.setAttribute("alt","Pay with PayPal");var r=["max-width: 100%","display: block","width: 100%","height: 100%","outline: none","border: 0"].join(";");n.style.cssText=r,t.appendChild(n),this.container.appendChild(t)},n.prototype.createCheckoutWithPayPalButton=function(){var t=document.createElement("script");t.src="//www.paypalobjects.com/api/button.js",t.async=!0,t.setAttribute("data-merchant",this.options.merchantId),t.setAttribute("data-button","checkout"),t.setAttribute("data-type","button"),t.setAttribute("data-width","150"),t.setAttribute("data-height","44"),t.setAttribute("data-lc",r(this.options.locale)),this.container.appendChild(t)},n.prototype.show=function(){this.container.style.display="block"},n.prototype.hide=function(){this.container.style.display="none"},e.exports=n},{"../shared/constants":170,"../shared/get-locale":172,"braintree-utilities":165}],169:[function(t,e){function n(t,e){this.popup=t,this.assetsUrl=e,this.spriteSrc=this.assetsUrl+"/pwpp/"+r.VERSION+"/images/pp_overlay_sprite.png",this._create(),this._setupEvents(),this._pollForPopup()}var i=t("braintree-utilities"),r=t("../shared/constants");n.prototype.render=function(){document.body.contains(this.el)||document.body.appendChild(this.el)},n.prototype.remove=function(){document.body.contains(this.el)&&document.body.removeChild(this.el)},n.prototype._create=function(){this.el=document.createElement("div"),this.el.className="bt-overlay",this._setStyles(this.el,["z-index: 20001","position: fixed","top: 0","left: 0","height: 100%","width: 100%","text-align: center","background: #000","background: rgba(0,0,0,0.7)",'-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=52)"']),this.el.appendChild(this._createCloseIcon()),this.el.appendChild(this._createMessage())},n.prototype._createCloseIcon=function(){return this.closeIcon=document.createElement("div"),this.closeIcon.className="bt-close-overlay",this._setStyles(this.closeIcon,["position: absolute","top: 10px","right: 10px","cursor: pointer","background: url("+this.spriteSrc+") no-repeat 0 -67px","height: 14px","width: 14px"]),this.closeIcon},n.prototype._createMessage=function(){var t=document.createElement("div");return this._setStyles(t,["position: relative","top: 50%","max-width: 350px",'font-family: "HelveticaNeue", "HelveticaNeue-Light", "Helvetica Neue Light", helvetica, arial, sans-serif',"font-size: 14px","line-height: 20px","margin: -70px auto 0"]),t.appendChild(this._createLogo()),t.appendChild(this._createExplanation()),t.appendChild(this._createFocusLink()),t},n.prototype._createExplanation=function(){var t=document.createElement("div");return this._setStyles(t,["color: #FFF","margin-bottom: 20px"]),t.innerHTML="Don't see the secure PayPal browser? We'll help you re-launch the window to complete your purchase.",t},n.prototype._createLogo=function(){var t=document.createElement("div");return this._setStyles(t,["background: url("+this.spriteSrc+") no-repeat 0 0","width: 94px","height: 25px","margin: 0 auto 26px auto"]),t},n.prototype._createFocusLink=function(){return this.focusLink=document.createElement("a"),this._setStyles(this.focusLink,["color: #009be1","cursor: pointer"]),this.focusLink.innerHTML="Continue",this.focusLink},n.prototype._setStyles=function(t,e){var n=e.join(";");t.style.cssText=n},n.prototype._setupEvents=function(){i.addEventListener(this.closeIcon,"click",i.bind(this._handleClose,this)),i.addEventListener(this.focusLink,"click",i.bind(this._handleFocus,this))},n.prototype._handleClose=function(t){t.preventDefault(),this.remove(),this.popup.close()},n.prototype._handleFocus=function(t){t.preventDefault(),this.popup.focus()},n.prototype._pollForPopup=function(){var t=setInterval(i.bind(function(){this.popup&&this.popup.closed&&(clearInterval(t),this.remove())},this),100)},e.exports=n},{"../shared/constants":170,"braintree-utilities":165}],170:[function(t,e,n){var i="1.3.4";n.VERSION=i,n.POPUP_NAME="braintree_paypal_popup",n.ARIES_POPUP_NAME="PPFrameRedirect",n.FRAME_NAME="braintree-paypal-frame",n.ARIES_FRAME_NAME="PPFrameRedirect",n.POPUP_PATH="/pwpp/"+i+"/html/braintree-frame.html",n.POPUP_OPTIONS="resizable,scrollbars",n.POPUP_HEIGHT=470,n.POPUP_WIDTH=410,n.ARIES_POPUP_HEIGHT=535,n.ARIES_POPUP_WIDTH=450,n.BRIDGE_FRAME_NAME="bt-proxy-frame",n.ARIES_SUPPORTED_CURRENCIES=["USD","GBP","EUR","AUD","CAD"],n.ARIES_SUPPORTED_COUNTRIES=["US","GB","AU","CA","ES","FR","DE","IT"],n.NONCE_TYPE="PayPalAccount",n.ILLEGAL_XHR_ERROR="Illegal XHR request attempted"},{}],171:[function(t,e){"use strict";e.exports={us:"en_us",gb:"en_uk",uk:"en_uk",de:"de_de",fr:"fr_fr",it:"it_it",es:"es_es",ca:"en_ca",au:"en_au",at:"de_de",be:"en_us",ch:"de_de",dk:"da_dk",nl:"nl_nl",no:"no_no",pl:"pl_pl",se:"sv_se",tr:"tr_tr",bg:"en_us",cy:"en_us",hr:"en_us",is:"en_us",kh:"en_us",mt:"en_us",my:"en_us",ru:"ru_ru"}},{}],172:[function(t,e){"use strict";function n(t){return-1!==t.indexOf("_")&&5===t.length}function i(t){var e;for(var n in o)o.hasOwnProperty(n)&&(n===t?e=o[n]:o[n]===t&&(e=o[n]));return e}function r(t){var e;if(t=t?t.toLowerCase():"us",t=t.replace(/-/g,"_"),e=n(t)?t:i(t)){var r=e.split("_");return[r[0],r[1].toUpperCase()].join("_")}return"en_US"}var o=t("../shared/data/country-code-lookup");e.exports=r},{"../shared/data/country-code-lookup":171}],173:[function(t,e){function n(){return c.matchUserAgent("Android")&&!i()}function i(){return c.matchUserAgent("Chrome")||c.matchUserAgent("CriOS")}function r(){return c.matchUserAgent("Firefox")}function o(){return c.matchUserAgent("Trident")||c.matchUserAgent("MSIE")}function s(){return c.matchUserAgent("Opera")||c.matchUserAgent("OPR")}function a(){return s()&&"[object OperaMini]"===l.call(window.operamini)}function u(){return c.matchUserAgent("Safari")&&!i()&&!n()}var c=t("./useragent"),l=Object.prototype.toString;e.exports={isAndroid:n,isChrome:i,isFirefox:r,isIE:o,isOpera:s,isOperaMini:a,isSafari:u}},{"./useragent":176}],174:[function(t,e){function n(){return!i()&&(s.isAndroid()||s.isIpod()||s.isIphone()||o.matchUserAgent("IEMobile"))}function i(){return s.isIpad()||s.isAndroid()&&!o.matchUserAgent("Mobile")}function r(){return!n()&&!i()}var o=t("./useragent"),s=t("./platform");e.exports={isMobile:n,isTablet:i,isDesktop:r}},{"./platform":175,"./useragent":176}],175:[function(t,e){function n(){return a.matchUserAgent("Android")}function i(){return a.matchUserAgent("iPad")}function r(){return a.matchUserAgent("iPod")}function o(){return a.matchUserAgent("iPhone")&&!r()}function s(){return i()||r()||o()}var a=t("./useragent");e.exports={isAndroid:n,isIpad:i,isIpod:r,isIphone:o,isIos:s}},{"./useragent":176}],176:[function(t,e,n){function i(){return o}function r(t){var e=n.getNativeUserAgent(),i=e.match(t);return i?!0:!1}var o=window.navigator.userAgent;n.getNativeUserAgent=i,n.matchUserAgent=r},{}],177:[function(t,e){function n(){return i()&&window.outerWidth<600}function i(){return f.test(d)}function r(){return!!window.postMessage}function o(){if(c.isOperaMini())return!1;if(l.isDesktop())return!0;if(l.isMobile()||l.isTablet()){if(c.isIE())return!1;if(p.isAndroid())return!0;if(p.isIos())return c.isSafari()&&h.matchUserAgent(/OS (?:8_1|8_0|8)(?!_\d)/i)||c.isChrome()?!1:!0}return!1}function s(){if(c.isIE()&&h.matchUserAgent(/MSIE 8\.0/))return!1;try{return window.self===window.top}catch(t){return!1}}function a(){return c.isIE()&&!u()}function u(){var t=null,e="";try{new ActiveXObject("")}catch(n){e=n.name}try{t=!!new ActiveXObject("htmlfile")}catch(n){t=!1}return t="ReferenceError"!==e&&t===!1?!1:!0,!t}var c=t("../useragent/browser"),l=t("../useragent/device"),p=t("../useragent/platform"),h=t("../useragent/useragent"),d=window.navigator.userAgent,f=/[Mm]obi|tablet|iOS|Android|IEMobile|Windows\sPhone/;e.exports={isMobile:n,isMobileDevice:i,detectedPostMessage:r,isPopupSupported:o,isOverlaySupported:s,isProxyFrameRequired:a}},{"../useragent/browser":173,"../useragent/device":174,"../useragent/platform":175,"../useragent/useragent":176}],178:[function(t,e){function n(t,e){var n="innerText";document&&document.body&&"textContent"in document.body&&(n="textContent"),t[n]=e}e.exports={setTextContent:n}},{}],179:[function(t,e){function n(){for(var t="",e=0;32>e;e++){var n=Math.floor(16*Math.random());t+=n.toString(16)}return t}function i(t){return/^(true|1)$/i.test(t)}function r(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\"/g,""").replace(/\'/g,"'")}function o(t){var e=t.indexOf("?"),n={};if(e>=0&&(t=t.substr(e+1)),0!==t.length){for(var i=t.split("&"),r=0,o=i.length;o>r;r++){var s=i[r],a=s.indexOf("="),u=s.substr(0,a),c=s.substr(a+1),l=decodeURIComponent(c);l=l.replace(/</g,"<").replace(/>/g,">"),"false"===l&&(l=!1),(void 0===l||"true"===l)&&(l=!0),n[u]=l}return n}}function s(t){return t&&"[object Function]"===Object.prototype.toString.call(t)}var a="function"==typeof String.prototype.trim?function(t){return t.trim()}:function(t){return t.replace(/^\s+|\s+$/,"")},u="function"==typeof window.btoa?function(t){return window.btoa(t)}:function(t){for(var e,n,i,r,o,s,a,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c="",l=0;l<t.length;)e=t.charCodeAt(l++),n=t.charCodeAt(l++),i=t.charCodeAt(l++),r=e>>2,o=(3&e)<<4|n>>4,s=(15&n)<<2|i>>6,a=63&i,isNaN(n)?s=a=64:isNaN(i)&&(a=64),c=c+u.charAt(r)+u.charAt(o)+u.charAt(s)+u.charAt(a);return c};e.exports={trim:a,btoa:u,generateUid:n,castToBoolean:i,htmlEscape:r,parseUrlParams:o,isFunction:s}},{}],180:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":190,dup:25}],181:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":190,dup:26}],182:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],183:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":190,dup:28}],184:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":190,dup:29}],185:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":180,"./lib/pubsub-client":181,"./lib/pubsub-server":182,"./lib/rpc-client":183,"./lib/rpc-server":184,dup:30}],186:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],187:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],188:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],189:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],190:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":186,"./lib/events":187,"./lib/fn":188,"./lib/url":189,dup:19}],191:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],192:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],193:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],194:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],195:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":191,"./lib/events":192,"./lib/fn":193,"./lib/url":194,dup:19}],196:[function(t,e){"use strict";function n(t){this.apiClient=t}var i=["getCreditCards","unlockCreditCard","sendAnalyticsEvents"];n.prototype.attach=function(t){function e(e){t.define(e,function(){n.apiClient[e].apply(n.apiClient,arguments)})}var n=this,r=0,o=i.length;for(r;o>r;r++)e(i[r])},e.exports=n},{}],197:[function(t,e){"use strict";function n(t,e){var n=window.getComputedStyle?getComputedStyle(t):t.currentStyle;return n[e]}function i(){return{html:{height:s.style.height||"",overflow:n(s,"overflow"),position:n(s,"position")},body:{height:a.style.height||"",overflow:n(a,"overflow")}}}function r(){var t=/Android|iPhone|iPod|iPad/i.test(window.navigator.userAgent);return t}function o(t){var e,n,i;this.encodedClientToken=t.clientToken,this.paypalOptions=t.paypal,this.container=null,this.merchantFormManager=null,this.root=t.root,this.configurationRequests=[],this.braintreeApiClient=u.configure({clientToken:t.clientToken,integration:"dropin"}),this.paymentMethodNonceReceivedCallback=t.paymentMethodNonceReceived,this.clientToken=u.parseClientToken(t.clientToken),this.bus=new l.MessageBus(this.root),this.rpcServer=new l.RPCServer(this.bus),this.apiProxyServer=new h(this.braintreeApiClient),this.apiProxyServer.attach(this.rpcServer),e=t.inlineFramePath||this.clientToken.assetsUrl+"/dropin/"+g+"/inline-frame.html",n=t.modalFramePath||this.clientToken.assetsUrl+"/dropin/"+g+"/modal-frame.html",s=document.documentElement,a=document.body,this.frames={inline:this._createFrame(e,"braintree-dropin-frame"),modal:this._createFrame(n,"braintree-dropin-modal-frame")},this.container=p.normalizeElement(t.container,"Unable to find valid container."),i=p.normalizeElement(t.form||this._findClosest(this.container,"form")),this.merchantFormManager=new d({form:i,frames:this.frames,onSubmit:this.paymentMethodNonceReceivedCallback,apiClient:this.braintreeApiClient}).initialize(),this.clientToken.paypalEnabled&&this.clientToken.paypal&&(p.isBrowserHttps()||this.clientToken.paypal.allowHttp)&&this._configurePayPal(),this.braintreeApiClient.sendAnalyticsEvents("dropin.web.initialized")}var s,a,u=t("braintree-api"),c=t("braintree-bus"),l=t("braintree-rpc"),p=t("braintree-utilities"),h=t("./api-proxy-server"),d=t("./merchant-form-manager"),f=t("./frame-container"),m=t("../shared/paypal-service"),y=t("braintree-paypal/src/shared/util/browser"),g="1.3.7";o.prototype.initialize=function(){var t=this;this._initializeModal(),this.container.appendChild(this.frames.inline.element),a.appendChild(this.frames.modal.element),this.rpcServer.define("receiveSharedCustomerIdentifier",function(e){t.braintreeApiClient.attrs.sharedCustomerIdentifier=e,t.braintreeApiClient.attrs.sharedCustomerIdentifierType="browser_session_cookie_store";for(var n=0;n<t.configurationRequests.length;n++)t.configurationRequests[n](t.encodedClientToken);t.configurationRequests=[]}),c.on(c.events.PAYMENT_METHOD_GENERATED,p.bind(this._handleAltPayData,this)),this.rpcServer.define("getConfiguration",function(e){e({clientToken:t.encodedClientToken,merchantHttps:p.isBrowserHttps()})}),this.rpcServer.define("getPayPalOptions",function(e){e(t.paypalOptions)}),this.rpcServer.define("selectPaymentMethod",function(e){t.frames.modal.rpcClient.invoke("selectPaymentMethod",[e]),t._showModal()}),this.rpcServer.define("sendAddedPaymentMethod",function(e){t.merchantFormManager.setNoncePayload(e),t.frames.inline.rpcClient.invoke("receiveNewPaymentMethod",[e])}),this.rpcServer.define("sendUsedPaymentMethod",function(e){t.frames.inline.rpcClient.invoke("selectPaymentMethod",[e])}),this.rpcServer.define("sendUnlockedNonce",function(e){t.merchantFormManager.setNoncePayload(e)}),this.rpcServer.define("clearNonce",function(){t.merchantFormManager.clearNoncePayload()}),this.rpcServer.define("closeDropInModal",function(){t._hideModal()}),this.rpcServer.define("setInlineFrameHeight",function(e){t.frames.inline.element.style.height=e+"px"}),this.bus.register("ready",function(e){e.source===t.frames.inline.element.contentWindow?t.frames.inline.rpcClient=new l.RPCClient(t.bus,e.source):e.source===t.frames.modal.element.contentWindow&&(t.frames.modal.rpcClient=new l.RPCClient(t.bus,e.source))})},o.prototype._createFrame=function(t,e){return new f(t,e)},o.prototype._initializeModal=function(){this.frames.modal.element.style.display="none",this.frames.modal.element.style.position=r()?"absolute":"fixed",this.frames.modal.element.style.top="0",this.frames.modal.element.style.left="0",this.frames.modal.element.style.height="100%",this.frames.modal.element.style.width="100%"},o.prototype._lockMerchantWindowSize=function(){setTimeout(function(){s.style.overflow="hidden",a.style.overflow="hidden",a.style.height="100%",r()&&(s.style.position="relative",s.style.height=window.innerHeight+"px")},160)},o.prototype._unlockMerchantWindowSize=function(){var t=this.merchantPageDefaultStyles;a.style.height=t.body.height,a.style.overflow=t.body.overflow,s.style.overflow=t.html.overflow,r()&&(s.style.height=t.html.height,s.style.position=t.html.position)},o.prototype._showModal=function(){var t=this,e=this.frames.modal.element;this.merchantPageDefaultStyles=i(),e.style.display="block",this.frames.modal.rpcClient.invoke("open",[],function(){setTimeout(function(){t._lockMerchantWindowSize(),e.contentWindow.focus()},200)})},o.prototype._hideModal=function(){this._unlockMerchantWindowSize(),this.frames.modal.element.style.display="none"},o.prototype._configurePayPal=function(){y.isPopupSupported()||(this.ppClient=new m({clientToken:this.clientToken,paypal:this.paypalOptions}),this.rpcServer.define("openPayPalModal",p.bind(this.ppClient._openModal,this.ppClient))),this.rpcServer.define("receivePayPalData",p.bind(this._handleAltPayData,this))},o.prototype._handleAltPayData=function(t){this.merchantFormManager.setNoncePayload(t),this.frames.inline.rpcClient.invoke("receiveNewPaymentMethod",[t]),this.frames.modal.rpcClient.invoke("modalViewClose")},o.prototype._findClosest=function(t,e){e=e.toUpperCase();do if(t.nodeName===e)return t;while(t=t.parentNode);throw"Unable to find a valid "+e},e.exports=o},{"../shared/paypal-service":201,"./api-proxy-server":196,"./frame-container":199,"./merchant-form-manager":200,"braintree-api":77,"braintree-bus":105,"braintree-paypal/src/shared/util/browser":177,"braintree-rpc":185,"braintree-utilities":195}],198:[function(t,e){"use strict";function n(t,e){e.clientToken=t;var n=new i(e);return n.initialize(),n}var i=t("./client"),r="1.3.7";e.exports={create:n,VERSION:r}},{"./client":197}],199:[function(t,e){"use strict";function n(t,e){this.element=document.createElement("iframe"),this.element.setAttribute("name",e),this.element.setAttribute("allowtransparency","true"),this.element.setAttribute("width","100%"),this.element.setAttribute("height","68"),this.element.setAttribute("style","-webkit-transition: height 210ms cubic-bezier(0.390, 0.575, 0.565, 1.000); -moz-transition: height 210ms cubic-bezier(0.390, 0.575, 0.565, 1.000); -ms-transition: height 210ms cubic-bezier(0.390, 0.575, 0.565, 1.000); -o-transition: height 210ms cubic-bezier(0.390, 0.575, 0.565, 1.000); transition: height 210ms cubic-bezier(0.390, 0.575, 0.565, 1.000);"),this.element.src=t,this.element.setAttribute("frameborder","0"),this.element.setAttribute("allowtransparency","true"),this.element.style.border="0",this.element.style.zIndex="9999"}e.exports=n},{}],200:[function(t,e){"use strict";function n(t){this.form=t.form,this.frames=t.frames,this.onSubmit=t.onSubmit,this.apiClient=t.apiClient}var i=t("braintree-utilities");n.prototype.initialize=function(){return this._isSubmitBased()&&this._setElements(),this._setEvents(),this},n.prototype.setNoncePayload=function(t){this.noncePayload=t},n.prototype.clearNoncePayload=function(){this.noncePayload=null},n.prototype._isSubmitBased=function(){return!this.onSubmit},n.prototype._isCallbackBased=function(){return!!this.onSubmit},n.prototype._setElements=function(){if(!this.form.payment_method_nonce){var t=document.createElement("input");t.type="hidden",t.name="payment_method_nonce",this.form.appendChild(t)}this.nonceField=this.form.payment_method_nonce},n.prototype._setEvents=function(){var t=this;i.addEventListener(this.form,"submit",function(){t._handleFormSubmit.apply(t,arguments)})},n.prototype._handleFormSubmit=function(t){this._shouldSubmit()||(t&&t.preventDefault?t.preventDefault():t.returnValue=!1,this.noncePayload&&this.noncePayload.nonce?this._handleNonceReply(t):this.frames.inline.rpcClient.invoke("requestNonce",[],i.bind(function(e){this.setNoncePayload(e),this._handleNonceReply(t)},this)))},n.prototype._shouldSubmit=function(){return this._isCallbackBased()?!1:this.nonceField.value.length>0},n.prototype._handleNonceReply=function(t){this._isCallbackBased()?this.apiClient.sendAnalyticsEvents("dropin.web.end.callback",i.bind(function(){var e=this.noncePayload;e.originalEvent=t,this.onSubmit(e),setTimeout(i.bind(function(){this.frames.inline.rpcClient.invoke("clearLoadingState")},this),200)},this)):this._triggerFormSubmission()},n.prototype._triggerFormSubmission=function(){this.nonceField.value=this.noncePayload.nonce,this.apiClient.sendAnalyticsEvents("dropin.web.end.auto-submit",i.bind(function(){"function"==typeof this.form.submit?this.form.submit():this.form.querySelector('[type="submit"]').click()},this))},e.exports=n},{"braintree-utilities":195}],201:[function(t,e){"use strict";function n(t){var e=t.clientToken,n=t.paypal||{},r=new i(e,{container:document.createElement("div"),displayName:n.displayName,locale:n.locale,singleUse:n.singleUse,amount:n.amount,currency:n.currency,onSuccess:n.onSuccess,enableShippingAddress:n.enableShippingAddress,shippingAddressOverride:n.shippingAddressOverride});return r.initialize(),r}var i=t("braintree-paypal/src/external/client");e.exports=n},{"braintree-paypal/src/external/client":166}],202:[function(t,e){"use strict";function n(t,e,n){this.client=t,this.htmlForm=e,this.paymentMethodNonceInput=n,this.setNonce({}),this.hijackForm()}var i=t("braintree-utilities");n.prototype.hijackForm=function(){this.onSubmitHandler=i.bind(this.handleSubmit,this),i.addEventListener(this.htmlForm,"submit",this.onSubmitHandler)},n.prototype.handleSubmit=function(t){var e=this;return t.preventDefault?t.preventDefault():t.returnValue=!1,this.hasExternalNonce()?(this.scrubAllAttributes(),void this.onNonceReceived(null,this.getNonce())):void this.client.tokenizeCard(this.extractValues(),function(t,n,i){t||e.setNonce({nonce:n,type:i.type,details:i.details}),e.onNonceReceived(t,e.getNonce())})},n.prototype.setNonce=function(t){this.nonce=t},n.prototype.getNonce=function(){return this.nonce},n.prototype.writeNonceToDOM=function(){this.paymentMethodNonceInput.value=this.getNonce().nonce},n.prototype.isBraintreeNode=function(t){return 1===t.nodeType&&t.attributes["data-braintree-name"]},n.prototype.hasExternalNonce=function(){var t=this.getNonce(),e=t&&null!=t.type&&"CreditCard"!==t.type,n=this.htmlForm.querySelector('[data-braintree-name="number"]').value.length<1;return n&&t&&t.nonce&&e},n.prototype.onExternalNonceReceived=function(t){this.clearCardNumberInput(),this.setNonce(t)},n.prototype.onExternalNonceCancelled=function(){this.setNonce(null)},n.prototype.onNonceReceived=function(t){var e=this.htmlForm;if(t)throw new Error("Unable to process payments at this time.");i.removeEventListener(e,"submit",this.onSubmitHandler),this.writeNonceToDOM(),e.submit&&("function"==typeof e.submit||e.submit.call)?e.submit():setTimeout(function(){e.querySelector('[type="submit"]').click()},1)},n.prototype.scrubAllAttributes=function(){this.extractValues()},n.prototype.extractValues=function(t,e){e=e||{},t=t||this.htmlForm;var n,i,r=t.children;for(i=0;i<r.length;i++)if(n=r[i],this.isBraintreeNode(n)){var o=n.getAttribute("data-braintree-name");"postal_code"===o?e.billingAddress={postalCode:n.value}:e[o]=n.value,this.scrubAttributes(n)
|
5 |
+
}else n.children&&n.children.length>0&&this.extractValues(n,e);return e},n.prototype.scrubAttributes=function(t){try{t.attributes.removeNamedItem("name")}catch(e){}},n.prototype.clearCardNumberInput=function(){var t=this.htmlForm.querySelector('[data-braintree-name="number"]');t.value=""},e.exports=n},{"braintree-utilities":210}],203:[function(t,e){"use strict";e.exports=function(t){var e;if("object"==typeof t)return t;e="payment_method_nonce","string"==typeof t&&(e=t);var n=document.createElement("input");return n.name=e,n.type="hidden",n}},{}],204:[function(t,e){"use strict";e.exports=function(t){for(var e=t.getElementsByTagName("*"),n={},i=0;i<e.length;i++){var r=e[i].getAttribute("data-braintree-name");n[r]=!0}if(!n.number)throw new Error('Unable to find an input with data-braintree-name="number" in your form. Please add one.');if(n.expiration_date){if(n.expiration_month||n.expiration_year)throw new Error('You have inputs with data-braintree-name="expiration_date" AND data-braintree-name="expiration_(year|month)". Please use either "expiration_date" or "expiration_year" and "expiration_month".')}else{if(!n.expiration_month&&!n.expiration_year)throw new Error('Unable to find an input with data-braintree-name="expiration_date" in your form. Please add one.');if(!n.expiration_month)throw new Error('Unable to find an input with data-braintree-name="expiration_month" in your form. Please add one.');if(!n.expiration_year)throw new Error('Unable to find an input with data-braintree-name="expiration_year" in your form. Please add one.')}}},{}],205:[function(t,e){"use strict";function n(t,e){var n,s,a=document.getElementById(e.id);if(!a)throw new Error('Unable to find form with id: "'+e.id+'"');return r(a),n=o(e.paymentMethodNonceInputField),a.appendChild(n),s=new i(t,a,n)}var i=t("./lib/form"),r=t("./lib/validate-annotations"),o=t("./lib/get-nonce-input");e.exports={setup:n}},{"./lib/form":202,"./lib/get-nonce-input":203,"./lib/validate-annotations":204}],206:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],207:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],208:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],209:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],210:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":206,"./lib/events":207,"./lib/fn":208,"./lib/url":209,dup:19}],211:[function(t,e,n){arguments[4][2][0].apply(n,arguments)},{"./coinbase-account":212,"./credit-card":213,"./jsonp-driver":214,"./normalize-api-fields":216,"./parse-client-token":217,"./root-data":219,"./sepa-bank-account":220,"./sepa-mandate":221,"./util":222,"braintree-3ds":231,"braintree-utilities":250,dup:2}],212:[function(t,e,n){arguments[4][3][0].apply(n,arguments)},{dup:3}],213:[function(t,e,n){arguments[4][4][0].apply(n,arguments)},{dup:4}],214:[function(t,e,n){arguments[4][5][0].apply(n,arguments)},{"./jsonp":215,dup:5}],215:[function(t,e,n){arguments[4][6][0].apply(n,arguments)},{"./util":222,dup:6}],216:[function(t,e,n){arguments[4][7][0].apply(n,arguments)},{dup:7}],217:[function(t,e,n){arguments[4][8][0].apply(n,arguments)},{"./polyfill":218,dup:8}],218:[function(t,e,n){arguments[4][9][0].apply(n,arguments)},{dup:9}],219:[function(t,e,n){arguments[4][10][0].apply(n,arguments)},{"braintree-rpc":239,dup:10}],220:[function(t,e,n){arguments[4][11][0].apply(n,arguments)},{dup:11}],221:[function(t,e,n){arguments[4][12][0].apply(n,arguments)},{dup:12}],222:[function(t,e,n){arguments[4][13][0].apply(n,arguments)},{dup:13}],223:[function(t,e,n){arguments[4][14][0].apply(n,arguments)},{"./lib/client":211,"./lib/jsonp":215,"./lib/jsonp-driver":214,"./lib/parse-client-token":217,"./lib/util":222,dup:14}],224:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],225:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],226:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],227:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],228:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":224,"./lib/events":225,"./lib/fn":226,"./lib/url":227,dup:19}],229:[function(t,e,n){arguments[4][20][0].apply(n,arguments)},{"../shared/receiver":233,"braintree-utilities":228,dup:20}],230:[function(t,e,n){arguments[4][21][0].apply(n,arguments)},{"./authorization_service":229,"braintree-utilities":228,dup:21}],231:[function(t,e,n){arguments[4][22][0].apply(n,arguments)},{"./client":230,"./vendor/json2":232,dup:22}],232:[function(t,e,n){arguments[4][23][0].apply(n,arguments)},{dup:23}],233:[function(t,e,n){arguments[4][24][0].apply(n,arguments)},{"braintree-utilities":228,dup:24}],234:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":244,dup:25}],235:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":244,dup:26}],236:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],237:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":244,dup:28}],238:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":244,dup:29}],239:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":234,"./lib/pubsub-client":235,"./lib/pubsub-server":236,"./lib/rpc-client":237,"./lib/rpc-server":238,dup:30}],240:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],241:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],242:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],243:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],244:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":240,"./lib/events":241,"./lib/fn":242,"./lib/url":243,dup:19}],245:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],246:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],247:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],248:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],249:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],250:[function(t,e,n){arguments[4][41][0].apply(n,arguments)},{"./lib/dom":245,"./lib/events":246,"./lib/fn":247,"./lib/string":248,"./lib/url":249,dup:41}],251:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":261,dup:25}],252:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":261,dup:26}],253:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],254:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":261,dup:28}],255:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":261,dup:29}],256:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":251,"./lib/pubsub-client":252,"./lib/pubsub-server":253,"./lib/rpc-client":254,"./lib/rpc-server":255,dup:30}],257:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],258:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],259:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],260:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],261:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":257,"./lib/events":258,"./lib/fn":259,"./lib/url":260,dup:19}],262:[function(t,e,n){arguments[4][159][0].apply(n,arguments)},{dup:159}],263:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],264:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],265:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],266:[function(t,e,n){arguments[4][39][0].apply(n,arguments)},{dup:39}],267:[function(t,e,n){arguments[4][164][0].apply(n,arguments)},{"./array":262,dup:164}],268:[function(t,e,n){arguments[4][165][0].apply(n,arguments)},{"./lib/array":262,"./lib/dom":263,"./lib/events":264,"./lib/fn":265,"./lib/string":266,"./lib/url":267,dup:165}],269:[function(t,e,n){arguments[4][166][0].apply(n,arguments)},{"../shared/constants":274,"../shared/get-locale":276,"../shared/util/browser":281,"../shared/util/dom":282,"../shared/util/util":283,"./logged-in-view":271,"./logged-out-view":272,"./overlay-view":273,"braintree-api":223,"braintree-rpc":256,"braintree-utilities":268,dup:166}],270:[function(t,e){function n(t,e){if(!r.detectedPostMessage())return void("function"==typeof e.onUnsupported&&e.onUnsupported(new Error("unsupported browser detected")));var n=new i(t,e);return n.initialize(),n}var i=t("./client"),r=t("../shared/util/browser"),o="1.3.4";e.exports={create:n,_browser:r,VERSION:o}},{"../shared/util/browser":281,"./client":269}],271:[function(t,e,n){arguments[4][167][0].apply(n,arguments)},{"../shared/constants":274,dup:167}],272:[function(t,e,n){arguments[4][168][0].apply(n,arguments)},{"../shared/constants":274,"../shared/get-locale":276,"braintree-utilities":268,dup:168}],273:[function(t,e,n){arguments[4][169][0].apply(n,arguments)},{"../shared/constants":274,"braintree-utilities":268,dup:169}],274:[function(t,e,n){arguments[4][170][0].apply(n,arguments)},{dup:170}],275:[function(t,e,n){arguments[4][171][0].apply(n,arguments)},{dup:171}],276:[function(t,e,n){arguments[4][172][0].apply(n,arguments)},{"../shared/data/country-code-lookup":275,dup:172}],277:[function(t,e,n){arguments[4][173][0].apply(n,arguments)},{"./useragent":280,dup:173}],278:[function(t,e,n){arguments[4][174][0].apply(n,arguments)},{"./platform":279,"./useragent":280,dup:174}],279:[function(t,e,n){arguments[4][175][0].apply(n,arguments)},{"./useragent":280,dup:175}],280:[function(t,e,n){arguments[4][176][0].apply(n,arguments)},{dup:176}],281:[function(t,e,n){arguments[4][177][0].apply(n,arguments)},{"../useragent/browser":277,"../useragent/device":278,"../useragent/platform":279,"../useragent/useragent":280,dup:177}],282:[function(t,e,n){arguments[4][178][0].apply(n,arguments)},{dup:178}],283:[function(t,e,n){arguments[4][179][0].apply(n,arguments)},{dup:179}],284:[function(t,e,n){arguments[4][25][0].apply(n,arguments)},{"braintree-utilities":294,dup:25}],285:[function(t,e,n){arguments[4][26][0].apply(n,arguments)},{"braintree-utilities":294,dup:26}],286:[function(t,e,n){arguments[4][27][0].apply(n,arguments)},{dup:27}],287:[function(t,e,n){arguments[4][28][0].apply(n,arguments)},{"braintree-utilities":294,dup:28}],288:[function(t,e,n){arguments[4][29][0].apply(n,arguments)},{"braintree-utilities":294,dup:29}],289:[function(t,e,n){arguments[4][30][0].apply(n,arguments)},{"./lib/message-bus":284,"./lib/pubsub-client":285,"./lib/pubsub-server":286,"./lib/rpc-client":287,"./lib/rpc-server":288,dup:30}],290:[function(t,e,n){arguments[4][31][0].apply(n,arguments)},{dup:31}],291:[function(t,e,n){arguments[4][32][0].apply(n,arguments)},{dup:32}],292:[function(t,e,n){arguments[4][33][0].apply(n,arguments)},{dup:33}],293:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],294:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":290,"./lib/events":291,"./lib/fn":292,"./lib/url":293,dup:19}],295:[function(t,e,n){arguments[4][15][0].apply(n,arguments)},{dup:15}],296:[function(t,e,n){arguments[4][16][0].apply(n,arguments)},{dup:16}],297:[function(t,e,n){arguments[4][17][0].apply(n,arguments)},{dup:17}],298:[function(t,e,n){arguments[4][18][0].apply(n,arguments)},{dup:18}],299:[function(t,e,n){arguments[4][19][0].apply(n,arguments)},{"./lib/dom":295,"./lib/events":296,"./lib/fn":297,"./lib/url":298,dup:19}],300:[function(t,e){function n(t){var e={};if(t){for(var n in t)t.hasOwnProperty(n)&&(e[i(n)]=t[n]);return e}}function i(t){return t.replace(/([A-Z])/g,function(t){return"_"+t.toLowerCase()})}e.exports={convertToLegacyShippingAddress:n}},{}],301:[function(t,e){"use strict";e.exports={ROOT_SUCCESS_CALLBACK:"onPaymentMethodReceived",ROOT_ERROR_CALLBACK:"onError"}},{}],302:[function(t,e){"use strict";function n(t,e){return o.on(o.events.PAYMENT_METHOD_GENERATED,function(t){o.emit(o.events.PAYMENT_METHOD_RECEIVED,t)}),e.coinbase=e.coinbase||{},e.apiClient=new i.Client({clientToken:t,integration:"coinbase"}),r.create(e)}{var i=t("braintree-api"),r=t("braintree-coinbase"),o=t("braintree-bus");t("braintree-utilities")}e.exports={initialize:n}},{"braintree-api":14,"braintree-bus":42,"braintree-coinbase":45,"braintree-utilities":299}],303:[function(t,e){"use strict";function n(t,e){return function(n){return e in t&&u.isFunction(t[e][n])?t[e][n]:function(){}}}function i(t,e){var i,d=n(e,"paypal"),f=d("onSuccess"),m=d("onCancelled"),y=new r.Client({clientToken:t,integration:"custom"});return i=o.setup(y,e),u.isFunction(e[c.ROOT_SUCCESS_CALLBACK])&&(i.onNonceReceived=function(t,n){e[c.ROOT_SUCCESS_CALLBACK](p(n))}),e.paypal&&(e.paypal.paymentMethodNonceInputField||(e.paypal.paymentMethodNonceInputField=i.paymentMethodNonceInput),e.paypal.onSuccess=function(t){i.onExternalNonceReceived(t),f.apply(null,[t.nonce,t.details.email,h(t.details.shippingAddress)])},e.paypal.onCancelled=function(){i.onExternalNonceCancelled(),m()},s.create(t,e.paypal)),e.coinbase&&(e.apiClient=y,e.paypal&&delete e.paypal,l.on(l.events.PAYMENT_METHOD_GENERATED,function(t){i.onExternalNonceReceived(t)}),a.create(e)),i}var r=t("braintree-api"),o=t("braintree-form"),s=t("braintree-paypal"),a=t("braintree-coinbase"),u=t("braintree-utilities"),c=t("../constants"),l=t("braintree-bus"),p=t("../lib/sanitize-payload"),h=t("../compatibility").convertToLegacyShippingAddress;e.exports={initialize:i}},{"../compatibility":300,"../constants":301,"../lib/sanitize-payload":307,"braintree-api":14,"braintree-bus":42,"braintree-coinbase":45,"braintree-form":205,"braintree-paypal":270,"braintree-utilities":299}],304:[function(t,e){"use strict";function n(t){return s.isFunction(t.paymentMethodNonceReceived)?t.paymentMethodNonceReceived:null}function i(t){return s.isFunction(t[u.ROOT_SUCCESS_CALLBACK])}function r(t,e){var r=n(e),s=i(e);return(r||s)&&(e.paymentMethodNonceReceived=function(t){r&&r.apply(null,[t.originalEvent,t.nonce]),delete t.originalEvent,a.emit(a.events.PAYMENT_METHOD_RECEIVED,c(t))}),o.create(t,e)}var o=t("braintree-dropin"),s=t("braintree-utilities"),a=t("braintree-bus"),u=t("../constants"),c=t("../lib/sanitize-payload");e.exports={initialize:r}},{"../constants":301,"../lib/sanitize-payload":307,"braintree-bus":42,"braintree-dropin":198,"braintree-utilities":299}],305:[function(t,e){"use strict";e.exports={custom:t("./custom"),dropin:t("./dropin"),paypal:t("./paypal"),coinbase:t("./coinbase")}},{"./coinbase":302,"./custom":303,"./dropin":304,"./paypal":306}],306:[function(t,e){"use strict";function n(t){return"onSuccess"in t&&s.isFunction(t.onSuccess)?t.onSuccess:"paypal"in t&&s.isFunction(t.paypal.onSuccess)?t.paypal.onSuccess:null}function i(t){return s.isFunction(t[a.ROOT_SUCCESS_CALLBACK])}function r(t,e){var r=n(e),s=i(e);return(r||s)&&(e.onSuccess=function(t){r&&r.apply(null,[t.nonce,t.details.email,c(t.details.shippingAddress)]),u.emit(u.events.PAYMENT_METHOD_RECEIVED,t)}),o.create(t,e)}var o=t("braintree-paypal"),s=t("braintree-utilities"),a=t("../constants"),u=t("braintree-bus"),c=t("../compatibility").convertToLegacyShippingAddress;e.exports={initialize:r}},{"../compatibility":300,"../constants":301,"braintree-bus":42,"braintree-paypal":270,"braintree-utilities":299}],307:[function(t,e){"use strict";e.exports=function(t){return{nonce:t.nonce,details:t.details,type:t.type}}},{}],308:[function(t,e){(function(n){"use strict";var i="2.6.3",r=t("braintree-rpc"),o=new r.MessageBus(n),s=new r.RPCServer(o);e.exports=function(){s.define("getExternalData",function(t){t({sdkVersion:i,merchantAppId:n.location.href})})}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"braintree-rpc":289}],309:[function(t,e){"use strict";function n(){}function i(t){if("CONFIGURATION"===t.type)throw new Error(t.message);try{console.error(t)}catch(e){console.log("ERROR: "+t.message)}}function r(t,e,n){if(!(e in p))throw new Error(e+" is an unsupported integration");return l.isFunction(n[d.ROOT_SUCCESS_CALLBACK])&&(m=function(t){n[d.ROOT_SUCCESS_CALLBACK](f(t))}),l.isFunction(n[d.ROOT_ERROR_CALLBACK])&&(y=n[d.ROOT_ERROR_CALLBACK]),n.configuration=s.parseClientToken(t),h.on(h.events.ERROR,y),h.on(h.events.PAYMENT_METHOD_RECEIVED,m),h.on(h.events.CONFIGURATION_REQUEST,function(t){t(n)}),h.on(h.events.WARNING,function(t){try{console.warn(t)}catch(e){}}),p[e].initialize(t,n)}var o="2.6.3",s=t("braintree-api"),a=t("braintree-paypal"),u=t("braintree-dropin"),c=t("braintree-form"),l=t("braintree-utilities"),p=t("./integrations"),h=t("braintree-bus"),d=t("./constants"),f=t("./lib/sanitize-payload"),m=n,y=i;e.exports={api:s,cse:Braintree,paypal:a,dropin:u,Form:c,setup:r,VERSION:o}},{"./constants":301,"./integrations":305,"./lib/sanitize-payload":307,"braintree-api":14,"braintree-bus":42,"braintree-dropin":198,"braintree-form":205,"braintree-paypal":270,"braintree-utilities":299}]},{},[1])(1)});
|
js/gene/braintree/vzero.js
ADDED
@@ -0,0 +1,753 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
/**
|
3 |
+
* Magento Braintree functionality wrapped up into a neat class
|
4 |
+
*
|
5 |
+
* @class vZero
|
6 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
7 |
+
*/
|
8 |
+
var vZero = Class.create();
|
9 |
+
vZero.prototype = {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Initialize all our required variables that we'll need later on
|
13 |
+
*
|
14 |
+
* @param code The payment methods code
|
15 |
+
* @param clientToken The client token provided by the server
|
16 |
+
* @param threeDSecure Flag to determine whether 3D secure is active, this is verified server side
|
17 |
+
* @param billingName Billing name used in verification of the card
|
18 |
+
* @param billingPostcode Billing postcode also needed to verify the card
|
19 |
+
*/
|
20 |
+
initialize: function (code, clientToken, threeDSecure, billingName, billingPostcode, quoteUrl, tokenizeUrl) {
|
21 |
+
this.code = code;
|
22 |
+
this.clientToken = clientToken;
|
23 |
+
this.threeDSecure = threeDSecure;
|
24 |
+
|
25 |
+
if(billingName) {
|
26 |
+
this.billingName = billingName;
|
27 |
+
}
|
28 |
+
if(billingPostcode) {
|
29 |
+
this.billingPostcode = billingPostcode;
|
30 |
+
}
|
31 |
+
if(quoteUrl) {
|
32 |
+
this.quoteUrl = quoteUrl;
|
33 |
+
}
|
34 |
+
if(tokenizeUrl) {
|
35 |
+
this.tokenizeUrl = tokenizeUrl;
|
36 |
+
}
|
37 |
+
|
38 |
+
this.acceptedCards = false;
|
39 |
+
|
40 |
+
this.closeMethod = false;
|
41 |
+
},
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Init the vZero integration by starting a new version of the client
|
45 |
+
* If 3D secure is enabled we also listen out for window messages
|
46 |
+
*/
|
47 |
+
init: function() {
|
48 |
+
|
49 |
+
// Different environments depending on 3D secure
|
50 |
+
if(this.threeDSecure == true) {
|
51 |
+
|
52 |
+
// Add an event in for messages
|
53 |
+
if (window.addEventListener){
|
54 |
+
window.addEventListener("message", this.receiveMessage.bind(this), false);
|
55 |
+
} else {
|
56 |
+
window.attachEvent("onmessage", this.receiveMessage.bind(this));
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
this.client = new braintree.api.Client({clientToken: this.clientToken});
|
61 |
+
|
62 |
+
},
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Set the amount within the checkout, this is only used in the default integration
|
66 |
+
* For any other checkouts see the updateData method, this is used by 3D secure
|
67 |
+
*
|
68 |
+
* @param amount The grand total of the order
|
69 |
+
*/
|
70 |
+
setAmount: function(amount) {
|
71 |
+
this.amount = parseFloat(amount);
|
72 |
+
},
|
73 |
+
|
74 |
+
/**
|
75 |
+
* We sometimes need to set the billing name later on in the process
|
76 |
+
*
|
77 |
+
* @param billingName
|
78 |
+
*/
|
79 |
+
setBillingName: function(billingName) {
|
80 |
+
this.billingName = billingName;
|
81 |
+
},
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Return the billing name
|
85 |
+
*
|
86 |
+
* @returns {*}
|
87 |
+
*/
|
88 |
+
getBillingName: function() {
|
89 |
+
|
90 |
+
// If billingName is an object we're wanting to grab the data from elements
|
91 |
+
if(typeof this.billingName == 'object') {
|
92 |
+
|
93 |
+
// Combine them with a space
|
94 |
+
return this.combineElementsValues(this.billingName);
|
95 |
+
|
96 |
+
} else {
|
97 |
+
|
98 |
+
// Otherwise we can presume that the billing name is a string
|
99 |
+
return this.billingName;
|
100 |
+
}
|
101 |
+
},
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Same for billing postcode
|
105 |
+
*
|
106 |
+
* @param billingPostcode
|
107 |
+
*/
|
108 |
+
setBillingPostcode: function(billingPostcode) {
|
109 |
+
this.billingPostcode = billingPostcode;
|
110 |
+
},
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Return the billing name
|
114 |
+
*
|
115 |
+
* @returns {*}
|
116 |
+
*/
|
117 |
+
getBillingPostcode: function() {
|
118 |
+
|
119 |
+
// If billingName is an object we're wanting to grab the data from elements
|
120 |
+
if(typeof this.billingPostcode == 'object') {
|
121 |
+
|
122 |
+
// Combine them with a space
|
123 |
+
return this.combineElementsValues(this.billingPostcode);
|
124 |
+
|
125 |
+
} else {
|
126 |
+
|
127 |
+
// Otherwise we can presume that the billing name is a string
|
128 |
+
return this.billingPostcode;
|
129 |
+
}
|
130 |
+
},
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Push through the selected accepted cards from the admin
|
134 |
+
*
|
135 |
+
* @param cards
|
136 |
+
*/
|
137 |
+
setAcceptedCards: function(cards) {
|
138 |
+
this.acceptedCards = cards;
|
139 |
+
},
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Return the accepted cards
|
143 |
+
*
|
144 |
+
* @returns {boolean|*}
|
145 |
+
*/
|
146 |
+
getAcceptedCards: function() {
|
147 |
+
return this.acceptedCards;
|
148 |
+
},
|
149 |
+
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Combine elements values into a string
|
153 |
+
*
|
154 |
+
* @param elements
|
155 |
+
* @param seperator
|
156 |
+
* @returns {string}
|
157 |
+
*/
|
158 |
+
combineElementsValues: function(elements, seperator) {
|
159 |
+
|
160 |
+
// If no seperator is set use a space
|
161 |
+
if(!seperator) {
|
162 |
+
seperator = ' ';
|
163 |
+
}
|
164 |
+
|
165 |
+
// Loop through the elements and build up an array
|
166 |
+
var response = [];
|
167 |
+
elements.each(function(element, index) {
|
168 |
+
if($(element) !== undefined) {
|
169 |
+
response[index] = $(element).value;
|
170 |
+
}
|
171 |
+
});
|
172 |
+
|
173 |
+
// Join with a space
|
174 |
+
return response.join(seperator);
|
175 |
+
|
176 |
+
},
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Update the card type from a card number
|
180 |
+
*
|
181 |
+
* @param cardNumber The card number that the user has entered
|
182 |
+
*/
|
183 |
+
updateCardType: function(cardNumber) {
|
184 |
+
|
185 |
+
// Retrieve the card type
|
186 |
+
var cardType = vzero.getCardType(cardNumber);
|
187 |
+
|
188 |
+
if (cardType == 'card') {
|
189 |
+
// If we cannot detect which kind of card they're using remove the value from the select
|
190 |
+
$('gene_braintree_creditcard_cc_type').value = '';
|
191 |
+
} else {
|
192 |
+
// Update the validation field
|
193 |
+
$('gene_braintree_creditcard_cc_type').value = cardType;
|
194 |
+
}
|
195 |
+
|
196 |
+
// Check the image exists on the page
|
197 |
+
if($('card-type-image') != undefined) {
|
198 |
+
|
199 |
+
// Grab the skin image URL without the last part
|
200 |
+
var skinImageUrl = $('card-type-image').src.substring(0, $('card-type-image').src.lastIndexOf("/"));
|
201 |
+
|
202 |
+
// Rebuild the URL with the card type included, all card types are stored as PNG's
|
203 |
+
$('card-type-image').setAttribute('src', skinImageUrl + "/" + cardType + ".png");
|
204 |
+
|
205 |
+
}
|
206 |
+
|
207 |
+
},
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Create a new event upon the card number field
|
211 |
+
*/
|
212 |
+
observeCardType: function() {
|
213 |
+
|
214 |
+
if(!$$('[data-genebraintree-name="number"]').first() != undefined) {
|
215 |
+
|
216 |
+
// Observe any blurring on the form
|
217 |
+
Element.observe($$('[data-genebraintree-name="number"]').first(), 'keyup', function (event) {
|
218 |
+
vzero.updateCardType(this.value);
|
219 |
+
});
|
220 |
+
|
221 |
+
}
|
222 |
+
|
223 |
+
},
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Observe all Ajax requests, this is needed on certain checkouts
|
227 |
+
* where we're unable to easily inject into methods
|
228 |
+
*
|
229 |
+
* @param callback A defined callback function if needed
|
230 |
+
*/
|
231 |
+
observeAjaxRequests: function(callback) {
|
232 |
+
|
233 |
+
// For every ajax request on complete update various Braintree things
|
234 |
+
Ajax.Responders.register({
|
235 |
+
onComplete: function(transport) {
|
236 |
+
|
237 |
+
// Check the transport object has a URL and that it wasn't to our own controller
|
238 |
+
if(transport.url && transport.url.indexOf('braintree') == -1) {
|
239 |
+
|
240 |
+
// Some checkout implementations may require custom callbacks
|
241 |
+
if(callback) {
|
242 |
+
callback();
|
243 |
+
} else {
|
244 |
+
this.updateData();
|
245 |
+
}
|
246 |
+
}
|
247 |
+
}.bind(this)
|
248 |
+
});
|
249 |
+
|
250 |
+
},
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Make an Ajax request to the server and request up to date information regarding the quote
|
254 |
+
*
|
255 |
+
* @param callback A defined callback function if needed
|
256 |
+
*/
|
257 |
+
updateData: function(callback) {
|
258 |
+
|
259 |
+
// Make a new ajax request to the server
|
260 |
+
new Ajax.Request(
|
261 |
+
this.quoteUrl,
|
262 |
+
{
|
263 |
+
method:'post',
|
264 |
+
onSuccess: function(transport) {
|
265 |
+
|
266 |
+
// Verify we have some response text
|
267 |
+
if (transport && transport.responseText) {
|
268 |
+
|
269 |
+
// Parse as an object
|
270 |
+
try {
|
271 |
+
response = eval('(' + transport.responseText + ')');
|
272 |
+
}
|
273 |
+
catch (e) {
|
274 |
+
response = {};
|
275 |
+
}
|
276 |
+
|
277 |
+
if(response.billingName != undefined) {
|
278 |
+
this.billingName = response.billingName;
|
279 |
+
}
|
280 |
+
if(response.billingPostcode != undefined) {
|
281 |
+
this.billingPostcode = response.billingPostcode;
|
282 |
+
}
|
283 |
+
if(response.grandTotal != undefined) {
|
284 |
+
this.amount = response.grandTotal;
|
285 |
+
}
|
286 |
+
|
287 |
+
// If PayPal is active update it
|
288 |
+
if(typeof vzeroPaypal != "undefined") {
|
289 |
+
|
290 |
+
// Totals
|
291 |
+
if(response.grandTotal != undefined && response.currencyCode != undefined) {
|
292 |
+
vzeroPaypal.setPricing(response.grandTotal, response.currencyCode);
|
293 |
+
}
|
294 |
+
|
295 |
+
}
|
296 |
+
|
297 |
+
if(callback) {
|
298 |
+
callback(response);
|
299 |
+
}
|
300 |
+
}
|
301 |
+
}.bind(this)
|
302 |
+
}
|
303 |
+
);
|
304 |
+
|
305 |
+
},
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Handle the user closing the 3D secure interface
|
309 |
+
*
|
310 |
+
* @param event
|
311 |
+
* @todo this functionality is not officially documented, waiting for official release of onClose method
|
312 |
+
*/
|
313 |
+
receiveMessage: function(event) {
|
314 |
+
|
315 |
+
// If the user closed the window unset the load waiting
|
316 |
+
if(event.data == 'user_closed=true') {
|
317 |
+
|
318 |
+
// Is there a close method defined?
|
319 |
+
if(this.closeMethod) {
|
320 |
+
this.closeMethod();
|
321 |
+
} else {
|
322 |
+
checkout.setLoadWaiting(false);
|
323 |
+
}
|
324 |
+
}
|
325 |
+
},
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Allow custom checkouts to set a custom method for closing 3D secure
|
329 |
+
*
|
330 |
+
* @param callback A defined callback function if needed
|
331 |
+
*/
|
332 |
+
close3dSecureMethod: function(callback) {
|
333 |
+
this.closeMethod = callback;
|
334 |
+
},
|
335 |
+
|
336 |
+
/**
|
337 |
+
* If the user attempts to use a 3D secure vaulted card and then cancels the 3D
|
338 |
+
* window the nonce associated with that card will become invalid, due to this
|
339 |
+
* we have to tokenize all the 3D secure cards again
|
340 |
+
*
|
341 |
+
* @param callback A defined callback function if needed
|
342 |
+
*/
|
343 |
+
tokenize3dSavedCards: function(callback) {
|
344 |
+
|
345 |
+
// Check 3D is enabled
|
346 |
+
if(this.threeDSecure) {
|
347 |
+
|
348 |
+
// Verify we have elements with data-token
|
349 |
+
if($$('[data-token]').first() != undefined) {
|
350 |
+
|
351 |
+
// Gather our tokens
|
352 |
+
tokens = [];
|
353 |
+
$$('[data-token]').each(function (element, index) {
|
354 |
+
tokens[index] = element.getAttribute('data-token');
|
355 |
+
});
|
356 |
+
|
357 |
+
// Make a new ajax request to the server
|
358 |
+
new Ajax.Request(
|
359 |
+
this.tokenizeUrl,
|
360 |
+
{
|
361 |
+
method:'post',
|
362 |
+
onSuccess: function(transport) {
|
363 |
+
|
364 |
+
// Verify we have some response text
|
365 |
+
if (transport && transport.responseText) {
|
366 |
+
|
367 |
+
// Parse as an object
|
368 |
+
try {
|
369 |
+
response = eval('(' + transport.responseText + ')');
|
370 |
+
}
|
371 |
+
catch (e) {
|
372 |
+
response = {};
|
373 |
+
}
|
374 |
+
|
375 |
+
// Check the response was successful
|
376 |
+
if(response.success) {
|
377 |
+
|
378 |
+
// Loop through the returned tokens
|
379 |
+
$H(response.tokens).each(function (element) {
|
380 |
+
|
381 |
+
// If the token exists update it's nonce
|
382 |
+
if($$('[data-token="' + element.key + '"]').first() != undefined) {
|
383 |
+
$$('[data-token="' + element.key + '"]').first().setAttribute('data-threedsecure-nonce', element.value);
|
384 |
+
}
|
385 |
+
});
|
386 |
+
}
|
387 |
+
|
388 |
+
if(callback) {
|
389 |
+
callback(response);
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}.bind(this),
|
393 |
+
parameters: {'tokens': Object.toJSON(tokens)}
|
394 |
+
}
|
395 |
+
);
|
396 |
+
} else {
|
397 |
+
callback();
|
398 |
+
}
|
399 |
+
|
400 |
+
} else {
|
401 |
+
callback();
|
402 |
+
}
|
403 |
+
},
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Make a request to Braintree for 3D secure information
|
407 |
+
*
|
408 |
+
* @param options Contains any callback functions which have been set
|
409 |
+
*/
|
410 |
+
verify3dSecure: function(options) {
|
411 |
+
|
412 |
+
var threeDSecureRequest = {
|
413 |
+
amount: this.amount,
|
414 |
+
creditCard: {
|
415 |
+
number: $$('[data-genebraintree-name="number"]').first().value,
|
416 |
+
expirationMonth: $$('[data-genebraintree-name="expiration_month"]').first().value,
|
417 |
+
expirationYear: $$('[data-genebraintree-name="expiration_year"]').first().value,
|
418 |
+
cardholderName: this.getBillingName(),
|
419 |
+
billingAddress: {
|
420 |
+
postalCode: this.getBillingPostcode()
|
421 |
+
}
|
422 |
+
}
|
423 |
+
};
|
424 |
+
|
425 |
+
// If the CVV field exists include it
|
426 |
+
if($$('[data-genebraintree-name="cvv"]').first() != undefined) {
|
427 |
+
threeDSecureRequest.creditCard.cvv = $$('[data-genebraintree-name="cvv"]').first().value;
|
428 |
+
}
|
429 |
+
|
430 |
+
// Run the verify function on the braintree client
|
431 |
+
this.client.verify3DS(threeDSecureRequest, function (error, response) {
|
432 |
+
|
433 |
+
if (!error) {
|
434 |
+
|
435 |
+
// Store threeDSecure token and nonce in form
|
436 |
+
$('creditcard-payment-nonce').value = response.nonce;
|
437 |
+
|
438 |
+
// Run any callback functions
|
439 |
+
if(options.onSuccess) {
|
440 |
+
options.onSuccess();
|
441 |
+
}
|
442 |
+
} else {
|
443 |
+
|
444 |
+
// Show the error
|
445 |
+
alert(error.message);
|
446 |
+
|
447 |
+
if(options.onFailure) {
|
448 |
+
options.onFailure();
|
449 |
+
} else {
|
450 |
+
checkout.setLoadWaiting(false);
|
451 |
+
}
|
452 |
+
}
|
453 |
+
});
|
454 |
+
|
455 |
+
},
|
456 |
+
|
457 |
+
/**
|
458 |
+
* Verify a card stored in the vault
|
459 |
+
*
|
460 |
+
* @param options Contains any callback functions which have been set
|
461 |
+
*/
|
462 |
+
verify3dSecureVault: function(options) {
|
463 |
+
|
464 |
+
// Get the payment nonce
|
465 |
+
var paymentNonce = $$('#creditcard-saved-accounts input:checked[type=radio]').first().getAttribute('data-threedsecure-nonce');
|
466 |
+
|
467 |
+
if(paymentNonce) {
|
468 |
+
// Run the verify function on the braintree client
|
469 |
+
this.client.verify3DS({
|
470 |
+
amount: this.amount,
|
471 |
+
creditCard: paymentNonce
|
472 |
+
}, function (error, response) {
|
473 |
+
|
474 |
+
if (!error) {
|
475 |
+
|
476 |
+
// Store threeDSecure token and nonce in form
|
477 |
+
$('creditcard-payment-nonce').removeAttribute('disabled');
|
478 |
+
$('creditcard-payment-nonce').value = response.nonce;
|
479 |
+
|
480 |
+
// Run any callback functions
|
481 |
+
if (options.onSuccess) {
|
482 |
+
options.onSuccess();
|
483 |
+
}
|
484 |
+
} else {
|
485 |
+
|
486 |
+
// Show the error
|
487 |
+
alert(error.message);
|
488 |
+
|
489 |
+
if(options.onFailure) {
|
490 |
+
options.onFailure();
|
491 |
+
} else {
|
492 |
+
checkout.setLoadWaiting(false);
|
493 |
+
}
|
494 |
+
}
|
495 |
+
});
|
496 |
+
} else {
|
497 |
+
|
498 |
+
alert('No payment nonce present.');
|
499 |
+
|
500 |
+
if(options.onFailure) {
|
501 |
+
options.onFailure();
|
502 |
+
} else {
|
503 |
+
checkout.setLoadWaiting(false);
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
},
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Process a standard card request
|
511 |
+
*
|
512 |
+
* @param options Contains any callback functions which have been set
|
513 |
+
*/
|
514 |
+
processCard: function(options) {
|
515 |
+
|
516 |
+
var tokenizeRequest = {
|
517 |
+
number: $$('[data-genebraintree-name="number"]').first().value,
|
518 |
+
cardholderName: this.getBillingName(),
|
519 |
+
expirationMonth: $$('[data-genebraintree-name="expiration_month"]').first().value,
|
520 |
+
expirationYear: $$('[data-genebraintree-name="expiration_year"]').first().value,
|
521 |
+
billingAddress: {
|
522 |
+
postalCode: this.getBillingPostcode()
|
523 |
+
}
|
524 |
+
};
|
525 |
+
|
526 |
+
// If the CVV field exists include it
|
527 |
+
if($$('[data-genebraintree-name="cvv"]').first() != undefined) {
|
528 |
+
tokenizeRequest.cvv = $$('[data-genebraintree-name="cvv"]').first().value;
|
529 |
+
}
|
530 |
+
|
531 |
+
// Attempt to tokenize the card
|
532 |
+
this.client.tokenizeCard(tokenizeRequest, function (errors, nonce) {
|
533 |
+
|
534 |
+
if(!errors) {
|
535 |
+
// Update the nonce in the form
|
536 |
+
$('creditcard-payment-nonce').value = nonce;
|
537 |
+
|
538 |
+
// Run any callback functions
|
539 |
+
if(options.onSuccess) {
|
540 |
+
options.onSuccess();
|
541 |
+
}
|
542 |
+
} else {
|
543 |
+
// Handle errors
|
544 |
+
for (var i = 0; i < errors.length; i++) {
|
545 |
+
alert(errors[i].code + " " + errors[i].message);
|
546 |
+
}
|
547 |
+
|
548 |
+
if(options.onFailure) {
|
549 |
+
options.onFailure();
|
550 |
+
} else {
|
551 |
+
checkout.setLoadWaiting(false);
|
552 |
+
}
|
553 |
+
}
|
554 |
+
});
|
555 |
+
|
556 |
+
},
|
557 |
+
|
558 |
+
/**
|
559 |
+
* Conduct a regular expression check to determine card type automatically
|
560 |
+
*
|
561 |
+
* @param number
|
562 |
+
* @returns {string}
|
563 |
+
*/
|
564 |
+
getCardType: function(number) {
|
565 |
+
|
566 |
+
if (number.match(/^4/) != null)
|
567 |
+
return "VI";
|
568 |
+
|
569 |
+
if (number.match(/^(34|37)/) != null)
|
570 |
+
return "AE";
|
571 |
+
|
572 |
+
if (number.match(/^5[1-5]/) != null)
|
573 |
+
return "MC";
|
574 |
+
|
575 |
+
if (number.match(/^6011/) != null)
|
576 |
+
return "DI";
|
577 |
+
|
578 |
+
if (number.match(/^(?:2131|1800|35)/) != null)
|
579 |
+
return "JCB";
|
580 |
+
|
581 |
+
if (number.match(/^(5018|5020|5038|6304|67[0-9]{2})/) != null)
|
582 |
+
return "ME";
|
583 |
+
|
584 |
+
// Otherwise return the standard card
|
585 |
+
return "card";
|
586 |
+
},
|
587 |
+
|
588 |
+
/**
|
589 |
+
* Wrapper function which defines which method should be called
|
590 |
+
*
|
591 |
+
* verify3dSecureVault - used for verifying any vaulted card when 3D secure is enabled
|
592 |
+
* verify3dSecure - verify a normal card via 3D secure
|
593 |
+
* processCard - verify a normal card
|
594 |
+
*
|
595 |
+
* If the customer has choosen a vaulted card and 3D is disabled no client side interaction is needed
|
596 |
+
*
|
597 |
+
* @param options Object containing onSuccess, onFailure functions
|
598 |
+
*/
|
599 |
+
process: function(options) {
|
600 |
+
|
601 |
+
// We have to handle vaulted 3D secure cards differently
|
602 |
+
if ($('creditcard-saved-accounts') != undefined
|
603 |
+
&& $$('#creditcard-saved-accounts input:checked[type=radio]').first() != undefined
|
604 |
+
&& $$('#creditcard-saved-accounts input:checked[type=radio]').first().hasAttribute('data-threedsecure-nonce'))
|
605 |
+
{
|
606 |
+
// The user has selected a card stored via 3D secure
|
607 |
+
this.verify3dSecureVault(options);
|
608 |
+
|
609 |
+
} else if($('creditcard-saved-accounts') != undefined
|
610 |
+
&& $$('#creditcard-saved-accounts input:checked[type=radio]').first() != undefined
|
611 |
+
&& $$('#creditcard-saved-accounts input:checked[type=radio]').first().value !== 'other')
|
612 |
+
{
|
613 |
+
// No action required as we're using a saved card
|
614 |
+
if(options.onSuccess) {
|
615 |
+
options.onSuccess()
|
616 |
+
}
|
617 |
+
|
618 |
+
} else if(this.threeDSecure == true) {
|
619 |
+
|
620 |
+
// Standard 3D secure callback
|
621 |
+
this.verify3dSecure(options);
|
622 |
+
|
623 |
+
} else {
|
624 |
+
|
625 |
+
// Otherwise process the card normally
|
626 |
+
this.processCard(options);
|
627 |
+
}
|
628 |
+
}
|
629 |
+
|
630 |
+
};
|
631 |
+
|
632 |
+
/**
|
633 |
+
* Separate class to handle functionality around the vZero PayPal button
|
634 |
+
*
|
635 |
+
* @class vZeroPayPalButton
|
636 |
+
* @author Dave Macaulay <dave@gene.co.uk>
|
637 |
+
*/
|
638 |
+
var vZeroPayPalButton = Class.create();
|
639 |
+
vZeroPayPalButton.prototype = {
|
640 |
+
|
641 |
+
/**
|
642 |
+
* Initialize the PayPal button class
|
643 |
+
*
|
644 |
+
* @param clientToken Client token generated from server
|
645 |
+
* @param storeFrontName The store name to show within the PayPal modal window
|
646 |
+
* @param singleUse Should the system attempt to open in single payment mode?
|
647 |
+
* @param locale The locale for the pamynet
|
648 |
+
* @param futureSingleUse When using future payments should we process the transaction as a single payment?
|
649 |
+
*/
|
650 |
+
initialize: function (clientToken, storeFrontName, singleUse, locale, futureSingleUse) {
|
651 |
+
this.clientToken = clientToken;
|
652 |
+
this.storeFrontName = storeFrontName;
|
653 |
+
this.singleUse = singleUse;
|
654 |
+
this.locale = locale;
|
655 |
+
this.futureSingleUse = futureSingleUse;
|
656 |
+
|
657 |
+
this.PayPalClient = false;
|
658 |
+
},
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Update the pricing information for the PayPal button
|
662 |
+
* If the PayPalClient has already been created we also update the _clientOptions
|
663 |
+
* so the PayPal modal window displays the correct values
|
664 |
+
*
|
665 |
+
* @param amount The amount formatted to two decimal places
|
666 |
+
* @param currency The currency code
|
667 |
+
*/
|
668 |
+
setPricing: function(amount, currency) {
|
669 |
+
|
670 |
+
// Set them into the class
|
671 |
+
this.amount = parseFloat(amount);
|
672 |
+
this.currency = currency;
|
673 |
+
|
674 |
+
// If the client exists update the clientOptions
|
675 |
+
if(this.PayPalClient._clientOptions != undefined) {
|
676 |
+
this.PayPalClient._clientOptions.amount = parseFloat(amount);
|
677 |
+
this.PayPalClient._clientOptions.currency = currency;
|
678 |
+
}
|
679 |
+
},
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Inject the PayPal button into the document
|
683 |
+
*
|
684 |
+
* @param options Object containing onSuccess method
|
685 |
+
*/
|
686 |
+
addPayPalButton: function(options) {
|
687 |
+
|
688 |
+
// Build up our setup configuration
|
689 |
+
var setupConfiguration = {
|
690 |
+
container: "paypal-container",
|
691 |
+
paymentMethodNonceInputField: "paypal-payment-nonce",
|
692 |
+
displayName: this.storeFrontName,
|
693 |
+
onPaymentMethodReceived: function(obj) {
|
694 |
+
|
695 |
+
// If a callback is defined we're doing something crazy!
|
696 |
+
if(typeof options != 'undefined' && options.onSuccess) {
|
697 |
+
options.onSuccess(obj);
|
698 |
+
} else {
|
699 |
+
// Force check
|
700 |
+
payment.switchMethod('gene_braintree_paypal');
|
701 |
+
|
702 |
+
// Re-enable the form
|
703 |
+
$('paypal-payment-nonce').disabled = false;
|
704 |
+
|
705 |
+
// Remove the PayPal button
|
706 |
+
$('paypal-complete').remove();
|
707 |
+
|
708 |
+
// Submit the checkout steps
|
709 |
+
review.save();
|
710 |
+
}
|
711 |
+
|
712 |
+
},
|
713 |
+
onUnsupported: function() {
|
714 |
+
alert('Sadly your browser does not support purchasing with PayPal.');
|
715 |
+
}
|
716 |
+
};
|
717 |
+
|
718 |
+
// Detect single use
|
719 |
+
if(this.singleUse == true) {
|
720 |
+
|
721 |
+
setupConfiguration.singleUse = true;
|
722 |
+
setupConfiguration.amount = this.amount;
|
723 |
+
setupConfiguration.currency = this.currency;
|
724 |
+
setupConfiguration.locale = this.locale;
|
725 |
+
|
726 |
+
} else if(this.futureSingleUse == true) {
|
727 |
+
|
728 |
+
setupConfiguration.singleUse = true;
|
729 |
+
|
730 |
+
}
|
731 |
+
|
732 |
+
// Start a new version of the client and assign for later modifications
|
733 |
+
this.PayPalClient = braintree.setup(this.clientToken, "paypal", setupConfiguration);
|
734 |
+
},
|
735 |
+
|
736 |
+
/**
|
737 |
+
* Allow closing of the PayPal window
|
738 |
+
*
|
739 |
+
* @param callback A defined callback function if needed
|
740 |
+
*/
|
741 |
+
closePayPalWindow: function(callback) {
|
742 |
+
|
743 |
+
// Make sure the client is active
|
744 |
+
if(this.PayPalClient != undefined) {
|
745 |
+
this.PayPalClient._close();
|
746 |
+
|
747 |
+
if(callback) {
|
748 |
+
callback();
|
749 |
+
}
|
750 |
+
}
|
751 |
+
}
|
752 |
+
|
753 |
+
};
|
lib/Braintree.php
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PHP Library
|
4 |
+
*
|
5 |
+
* Braintree base class and initialization
|
6 |
+
* Provides methods to child classes. This class cannot be instantiated.
|
7 |
+
*
|
8 |
+
* PHP version 5
|
9 |
+
*
|
10 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
11 |
+
*/
|
12 |
+
|
13 |
+
|
14 |
+
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__)));
|
15 |
+
|
16 |
+
abstract class Braintree
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* @ignore
|
20 |
+
* don't permit an explicit call of the constructor!
|
21 |
+
* (like $t = new Braintree_Transaction())
|
22 |
+
*/
|
23 |
+
protected function __construct()
|
24 |
+
{
|
25 |
+
}
|
26 |
+
/**
|
27 |
+
* @ignore
|
28 |
+
* don't permit cloning the instances (like $x = clone $v)
|
29 |
+
*/
|
30 |
+
protected function __clone()
|
31 |
+
{
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* returns private/nonexistent instance properties
|
36 |
+
* @ignore
|
37 |
+
* @access public
|
38 |
+
* @param string $name property name
|
39 |
+
* @return mixed contents of instance properties
|
40 |
+
*/
|
41 |
+
public function __get($name)
|
42 |
+
{
|
43 |
+
if (array_key_exists($name, $this->_attributes)) {
|
44 |
+
return $this->_attributes[$name];
|
45 |
+
}
|
46 |
+
else {
|
47 |
+
trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE);
|
48 |
+
return null;
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* used by isset() and empty()
|
54 |
+
* @access public
|
55 |
+
* @param string $name property name
|
56 |
+
* @return boolean
|
57 |
+
*/
|
58 |
+
public function __isset($name)
|
59 |
+
{
|
60 |
+
return array_key_exists($name, $this->_attributes);
|
61 |
+
}
|
62 |
+
|
63 |
+
public function _set($key, $value)
|
64 |
+
{
|
65 |
+
$this->_attributes[$key] = $value;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
require_once('Braintree/Modification.php');
|
69 |
+
require_once('Braintree/Instance.php');
|
70 |
+
|
71 |
+
require_once('Braintree/Address.php');
|
72 |
+
require_once('Braintree/AddressGateway.php');
|
73 |
+
require_once('Braintree/AddOn.php');
|
74 |
+
require_once('Braintree/AddOnGateway.php');
|
75 |
+
require_once('Braintree/ApplePayCard.php');
|
76 |
+
require_once('Braintree/ClientToken.php');
|
77 |
+
require_once('Braintree/ClientTokenGateway.php');
|
78 |
+
require_once('Braintree/CoinbaseAccount.php');
|
79 |
+
require_once('Braintree/Collection.php');
|
80 |
+
require_once('Braintree/Configuration.php');
|
81 |
+
require_once('Braintree/CreditCard.php');
|
82 |
+
require_once('Braintree/CreditCardGateway.php');
|
83 |
+
require_once('Braintree/Customer.php');
|
84 |
+
require_once('Braintree/CustomerGateway.php');
|
85 |
+
require_once('Braintree/CustomerSearch.php');
|
86 |
+
require_once('Braintree/DisbursementDetails.php');
|
87 |
+
require_once('Braintree/Dispute.php');
|
88 |
+
require_once('Braintree/Dispute/TransactionDetails.php');
|
89 |
+
require_once('Braintree/Descriptor.php');
|
90 |
+
require_once('Braintree/Digest.php');
|
91 |
+
require_once('Braintree/Discount.php');
|
92 |
+
require_once('Braintree/DiscountGateway.php');
|
93 |
+
require_once('Braintree/IsNode.php');
|
94 |
+
require_once('Braintree/EqualityNode.php');
|
95 |
+
require_once('Braintree/Exception.php');
|
96 |
+
require_once('Braintree/Gateway.php');
|
97 |
+
require_once('Braintree/Http.php');
|
98 |
+
require_once('Braintree/KeyValueNode.php');
|
99 |
+
require_once('Braintree/MerchantAccount.php');
|
100 |
+
require_once('Braintree/MerchantAccountGateway.php');
|
101 |
+
require_once('Braintree/MerchantAccount/BusinessDetails.php');
|
102 |
+
require_once('Braintree/MerchantAccount/FundingDetails.php');
|
103 |
+
require_once('Braintree/MerchantAccount/IndividualDetails.php');
|
104 |
+
require_once('Braintree/MerchantAccount/AddressDetails.php');
|
105 |
+
require_once('Braintree/MultipleValueNode.php');
|
106 |
+
require_once('Braintree/MultipleValueOrTextNode.php');
|
107 |
+
require_once('Braintree/PartialMatchNode.php');
|
108 |
+
require_once('Braintree/Plan.php');
|
109 |
+
require_once('Braintree/PlanGateway.php');
|
110 |
+
require_once('Braintree/RangeNode.php');
|
111 |
+
require_once('Braintree/ResourceCollection.php');
|
112 |
+
require_once('Braintree/RiskData.php');
|
113 |
+
require_once('Braintree/SettlementBatchSummary.php');
|
114 |
+
require_once('Braintree/SettlementBatchSummaryGateway.php');
|
115 |
+
require_once('Braintree/SignatureService.php');
|
116 |
+
require_once('Braintree/Subscription.php');
|
117 |
+
require_once('Braintree/SubscriptionGateway.php');
|
118 |
+
require_once('Braintree/SubscriptionSearch.php');
|
119 |
+
require_once('Braintree/Subscription/StatusDetails.php');
|
120 |
+
require_once('Braintree/TextNode.php');
|
121 |
+
require_once('Braintree/Transaction.php');
|
122 |
+
require_once('Braintree/TransactionGateway.php');
|
123 |
+
require_once('Braintree/Disbursement.php');
|
124 |
+
require_once('Braintree/TransactionSearch.php');
|
125 |
+
require_once('Braintree/TransparentRedirect.php');
|
126 |
+
require_once('Braintree/TransparentRedirectGateway.php');
|
127 |
+
require_once('Braintree/Util.php');
|
128 |
+
require_once('Braintree/Version.php');
|
129 |
+
require_once('Braintree/Xml.php');
|
130 |
+
require_once('Braintree/Error/Codes.php');
|
131 |
+
require_once('Braintree/Error/ErrorCollection.php');
|
132 |
+
require_once('Braintree/Error/Validation.php');
|
133 |
+
require_once('Braintree/Error/ValidationErrorCollection.php');
|
134 |
+
require_once('Braintree/Exception/Authentication.php');
|
135 |
+
require_once('Braintree/Exception/Authorization.php');
|
136 |
+
require_once('Braintree/Exception/Configuration.php');
|
137 |
+
require_once('Braintree/Exception/DownForMaintenance.php');
|
138 |
+
require_once('Braintree/Exception/ForgedQueryString.php');
|
139 |
+
require_once('Braintree/Exception/InvalidSignature.php');
|
140 |
+
require_once('Braintree/Exception/NotFound.php');
|
141 |
+
require_once('Braintree/Exception/ServerError.php');
|
142 |
+
require_once('Braintree/Exception/SSLCertificate.php');
|
143 |
+
require_once('Braintree/Exception/SSLCaFileNotFound.php');
|
144 |
+
require_once('Braintree/Exception/Unexpected.php');
|
145 |
+
require_once('Braintree/Exception/UpgradeRequired.php');
|
146 |
+
require_once('Braintree/Exception/ValidationsFailed.php');
|
147 |
+
require_once('Braintree/Result/CreditCardVerification.php');
|
148 |
+
require_once('Braintree/Result/Error.php');
|
149 |
+
require_once('Braintree/Result/Successful.php');
|
150 |
+
require_once('Braintree/Test/CreditCardNumbers.php');
|
151 |
+
require_once('Braintree/Test/MerchantAccount.php');
|
152 |
+
require_once('Braintree/Test/TransactionAmounts.php');
|
153 |
+
require_once('Braintree/Test/VenmoSdk.php');
|
154 |
+
require_once('Braintree/Test/Nonces.php');
|
155 |
+
require_once('Braintree/Transaction/AddressDetails.php');
|
156 |
+
require_once('Braintree/Transaction/ApplePayCardDetails.php');
|
157 |
+
require_once('Braintree/Transaction/CoinbaseDetails.php');
|
158 |
+
require_once('Braintree/Transaction/CreditCardDetails.php');
|
159 |
+
require_once('Braintree/Transaction/PayPalDetails.php');
|
160 |
+
require_once('Braintree/Transaction/CustomerDetails.php');
|
161 |
+
require_once('Braintree/Transaction/StatusDetails.php');
|
162 |
+
require_once('Braintree/Transaction/SubscriptionDetails.php');
|
163 |
+
require_once('Braintree/WebhookNotification.php');
|
164 |
+
require_once('Braintree/WebhookTesting.php');
|
165 |
+
require_once('Braintree/Xml/Generator.php');
|
166 |
+
require_once('Braintree/Xml/Parser.php');
|
167 |
+
require_once('Braintree/CreditCardVerification.php');
|
168 |
+
require_once('Braintree/CreditCardVerificationGateway.php');
|
169 |
+
require_once('Braintree/CreditCardVerificationSearch.php');
|
170 |
+
require_once('Braintree/PartnerMerchant.php');
|
171 |
+
require_once('Braintree/PayPalAccount.php');
|
172 |
+
require_once('Braintree/PayPalAccountGateway.php');
|
173 |
+
require_once('Braintree/PaymentMethod.php');
|
174 |
+
require_once('Braintree/PaymentMethodGateway.php');
|
175 |
+
require_once('Braintree/PaymentMethodNonce.php');
|
176 |
+
require_once('Braintree/PaymentMethodNonceGateway.php');
|
177 |
+
require_once('Braintree/PaymentInstrumentType.php');
|
178 |
+
require_once('Braintree/UnknownPaymentMethod.php');
|
179 |
+
|
180 |
+
if (version_compare(PHP_VERSION, '5.2.1', '<')) {
|
181 |
+
throw new Braintree_Exception('PHP version >= 5.2.1 required');
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
+
function requireDependencies() {
|
186 |
+
$requiredExtensions = array('xmlwriter', 'SimpleXML', 'openssl', 'dom', 'hash', 'curl');
|
187 |
+
foreach ($requiredExtensions AS $ext) {
|
188 |
+
if (!extension_loaded($ext)) {
|
189 |
+
throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.');
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
requireDependencies();
|
lib/Braintree/AddOn.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_AddOn extends Braintree_Modification
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self();
|
7 |
+
$instance->_initialize($attributes);
|
8 |
+
return $instance;
|
9 |
+
}
|
10 |
+
|
11 |
+
|
12 |
+
// static methods redirecting to gateway
|
13 |
+
|
14 |
+
public static function all()
|
15 |
+
{
|
16 |
+
return Braintree_Configuration::gateway()->addOn()->all();
|
17 |
+
}
|
18 |
+
}
|
lib/Braintree/AddOnGateway.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_AddOnGateway
|
3 |
+
{
|
4 |
+
private $_gateway;
|
5 |
+
private $_config;
|
6 |
+
private $_http;
|
7 |
+
|
8 |
+
public function __construct($gateway)
|
9 |
+
{
|
10 |
+
$this->_gateway = $gateway;
|
11 |
+
$this->_config = $gateway->config;
|
12 |
+
$this->_http = new Braintree_Http($gateway->config);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function all()
|
16 |
+
{
|
17 |
+
$path = $this->_config->merchantPath() . '/add_ons';
|
18 |
+
$response = $this->_http->get($path);
|
19 |
+
|
20 |
+
$addOns = array("addOn" => $response['addOns']);
|
21 |
+
|
22 |
+
return Braintree_Util::extractAttributeAsArray(
|
23 |
+
$addOns,
|
24 |
+
'addOn'
|
25 |
+
);
|
26 |
+
}
|
27 |
+
}
|
lib/Braintree/Address.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Address module
|
4 |
+
* PHP Version 5
|
5 |
+
* Creates and manages Braintree Addresses
|
6 |
+
*
|
7 |
+
* An Address belongs to a Customer. It can be associated to a
|
8 |
+
* CreditCard as the billing address. It can also be used
|
9 |
+
* as the shipping address when creating a Transaction.
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*
|
14 |
+
* @property-read string $company
|
15 |
+
* @property-read string $countryName
|
16 |
+
* @property-read string $createdAt
|
17 |
+
* @property-read string $customerId
|
18 |
+
* @property-read string $extendedAddress
|
19 |
+
* @property-read string $firstName
|
20 |
+
* @property-read string $id
|
21 |
+
* @property-read string $lastName
|
22 |
+
* @property-read string $locality
|
23 |
+
* @property-read string $postalCode
|
24 |
+
* @property-read string $region
|
25 |
+
* @property-read string $streetAddress
|
26 |
+
* @property-read string $updatedAt
|
27 |
+
*/
|
28 |
+
class Braintree_Address extends Braintree
|
29 |
+
{
|
30 |
+
/**
|
31 |
+
* returns false if comparing object is not a Braintree_Address,
|
32 |
+
* or is a Braintree_Address with a different id
|
33 |
+
*
|
34 |
+
* @param object $other address to compare against
|
35 |
+
* @return boolean
|
36 |
+
*/
|
37 |
+
public function isEqual($other)
|
38 |
+
{
|
39 |
+
return !($other instanceof Braintree_Address) ?
|
40 |
+
false :
|
41 |
+
($this->id === $other->id && $this->customerId === $other->customerId);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* create a printable representation of the object as:
|
46 |
+
* ClassName[property=value, property=value]
|
47 |
+
* @ignore
|
48 |
+
* @return var
|
49 |
+
*/
|
50 |
+
public function __toString()
|
51 |
+
{
|
52 |
+
return __CLASS__ . '[' .
|
53 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* sets instance properties from an array of values
|
58 |
+
*
|
59 |
+
* @ignore
|
60 |
+
* @access protected
|
61 |
+
* @param array $addressAttribs array of address data
|
62 |
+
* @return none
|
63 |
+
*/
|
64 |
+
protected function _initialize($addressAttribs)
|
65 |
+
{
|
66 |
+
// set the attributes
|
67 |
+
$this->_attributes = $addressAttribs;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* factory method: returns an instance of Braintree_Address
|
72 |
+
* to the requesting method, with populated properties
|
73 |
+
* @ignore
|
74 |
+
* @return object instance of Braintree_Address
|
75 |
+
*/
|
76 |
+
public static function factory($attributes)
|
77 |
+
{
|
78 |
+
$instance = new self();
|
79 |
+
$instance->_initialize($attributes);
|
80 |
+
return $instance;
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
|
85 |
+
// static methods redirecting to gateway
|
86 |
+
|
87 |
+
public static function create($attribs)
|
88 |
+
{
|
89 |
+
return Braintree_Configuration::gateway()->address()->create($attribs);
|
90 |
+
}
|
91 |
+
|
92 |
+
public static function createNoValidate($attribs)
|
93 |
+
{
|
94 |
+
return Braintree_Configuration::gateway()->address()->createNoValidate($attribs);
|
95 |
+
}
|
96 |
+
|
97 |
+
public static function delete($customerOrId = null, $addressId = null)
|
98 |
+
{
|
99 |
+
return Braintree_Configuration::gateway()->address()->delete($customerOrId, $addressId);
|
100 |
+
}
|
101 |
+
|
102 |
+
public static function find($customerOrId, $addressId)
|
103 |
+
{
|
104 |
+
return Braintree_Configuration::gateway()->address()->find($customerOrId, $addressId);
|
105 |
+
}
|
106 |
+
|
107 |
+
public static function update($customerOrId, $addressId, $attributes)
|
108 |
+
{
|
109 |
+
return Braintree_Configuration::gateway()->address()->update($customerOrId, $addressId, $attributes);
|
110 |
+
}
|
111 |
+
|
112 |
+
public static function updateNoValidate($customerOrId, $addressId, $attributes)
|
113 |
+
{
|
114 |
+
return Braintree_Configuration::gateway()->address()->updateNoValidate($customerOrId, $addressId, $attributes);
|
115 |
+
}
|
116 |
+
}
|
lib/Braintree/AddressGateway.php
ADDED
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree AddressGateway module
|
4 |
+
* PHP Version 5
|
5 |
+
* Creates and manages Braintree Addresses
|
6 |
+
*
|
7 |
+
* An Address belongs to a Customer. It can be associated to a
|
8 |
+
* CreditCard as the billing address. It can also be used
|
9 |
+
* as the shipping address when creating a Transaction.
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_AddressGateway
|
15 |
+
{
|
16 |
+
private $_gateway;
|
17 |
+
private $_config;
|
18 |
+
private $_http;
|
19 |
+
|
20 |
+
public function __construct($gateway)
|
21 |
+
{
|
22 |
+
$this->_gateway = $gateway;
|
23 |
+
$this->_config = $gateway->config;
|
24 |
+
$this->_http = new Braintree_Http($gateway->config);
|
25 |
+
}
|
26 |
+
|
27 |
+
|
28 |
+
/* public class methods */
|
29 |
+
/**
|
30 |
+
*
|
31 |
+
* @access public
|
32 |
+
* @param array $attribs
|
33 |
+
* @return object Result, either Successful or Error
|
34 |
+
*/
|
35 |
+
public function create($attribs)
|
36 |
+
{
|
37 |
+
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
|
38 |
+
$customerId = isset($attribs['customerId']) ?
|
39 |
+
$attribs['customerId'] :
|
40 |
+
null;
|
41 |
+
|
42 |
+
$this->_validateCustomerId($customerId);
|
43 |
+
unset($attribs['customerId']);
|
44 |
+
return $this->_doCreate(
|
45 |
+
'/customers/' . $customerId . '/addresses',
|
46 |
+
array('address' => $attribs)
|
47 |
+
);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* attempts the create operation assuming all data will validate
|
52 |
+
* returns a Braintree_Address object instead of a Result
|
53 |
+
*
|
54 |
+
* @access public
|
55 |
+
* @param array $attribs
|
56 |
+
* @return object
|
57 |
+
* @throws Braintree_Exception_ValidationError
|
58 |
+
*/
|
59 |
+
public function createNoValidate($attribs)
|
60 |
+
{
|
61 |
+
$result = $this->create($attribs);
|
62 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
63 |
+
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* delete an address by id
|
68 |
+
*
|
69 |
+
* @param mixed $customerOrId
|
70 |
+
* @param string $addressId
|
71 |
+
*/
|
72 |
+
public function delete($customerOrId = null, $addressId = null)
|
73 |
+
{
|
74 |
+
$this->_validateId($addressId);
|
75 |
+
$customerId = $this->_determineCustomerId($customerOrId);
|
76 |
+
$path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
|
77 |
+
$this->_http->delete($path);
|
78 |
+
return new Braintree_Result_Successful();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* find an address by id
|
83 |
+
*
|
84 |
+
* Finds the address with the given <b>addressId</b> that is associated
|
85 |
+
* to the given <b>customerOrId</b>.
|
86 |
+
* If the address cannot be found, a NotFound exception will be thrown.
|
87 |
+
*
|
88 |
+
*
|
89 |
+
* @access public
|
90 |
+
* @param mixed $customerOrId
|
91 |
+
* @param string $addressId
|
92 |
+
* @return object Braintree_Address
|
93 |
+
* @throws Braintree_Exception_NotFound
|
94 |
+
*/
|
95 |
+
public function find($customerOrId, $addressId)
|
96 |
+
{
|
97 |
+
|
98 |
+
$customerId = $this->_determineCustomerId($customerOrId);
|
99 |
+
$this->_validateId($addressId);
|
100 |
+
|
101 |
+
try {
|
102 |
+
$path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
|
103 |
+
$response = $this->_http->get($path);
|
104 |
+
return Braintree_Address::factory($response['address']);
|
105 |
+
} catch (Braintree_Exception_NotFound $e) {
|
106 |
+
throw new Braintree_Exception_NotFound(
|
107 |
+
'address for customer ' . $customerId .
|
108 |
+
' with id ' . $addressId . ' not found.'
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* updates the address record
|
116 |
+
*
|
117 |
+
* if calling this method in context,
|
118 |
+
* customerOrId is the 2nd attribute, addressId 3rd.
|
119 |
+
* customerOrId & addressId are not sent in object context.
|
120 |
+
*
|
121 |
+
*
|
122 |
+
* @access public
|
123 |
+
* @param array $attributes
|
124 |
+
* @param mixed $customerOrId (only used in call)
|
125 |
+
* @param string $addressId (only used in call)
|
126 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
127 |
+
*/
|
128 |
+
public function update($customerOrId, $addressId, $attributes)
|
129 |
+
{
|
130 |
+
$this->_validateId($addressId);
|
131 |
+
$customerId = $this->_determineCustomerId($customerOrId);
|
132 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
|
133 |
+
|
134 |
+
$path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
|
135 |
+
$response = $this->_http->put($path, array('address' => $attributes));
|
136 |
+
|
137 |
+
return $this->_verifyGatewayResponse($response);
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* update an address record, assuming validations will pass
|
143 |
+
*
|
144 |
+
* if calling this method in context,
|
145 |
+
* customerOrId is the 2nd attribute, addressId 3rd.
|
146 |
+
* customerOrId & addressId are not sent in object context.
|
147 |
+
*
|
148 |
+
* @access public
|
149 |
+
* @param array $transactionAttribs
|
150 |
+
* @param string $customerId
|
151 |
+
* @return object Braintree_Transaction
|
152 |
+
* @throws Braintree_Exception_ValidationsFailed
|
153 |
+
* @see Braintree_Address::update()
|
154 |
+
*/
|
155 |
+
public function updateNoValidate($customerOrId, $addressId, $attributes)
|
156 |
+
{
|
157 |
+
$result = $this->update($customerOrId, $addressId, $attributes);
|
158 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* creates a full array signature of a valid create request
|
163 |
+
* @return array gateway create request format
|
164 |
+
*/
|
165 |
+
public static function createSignature()
|
166 |
+
{
|
167 |
+
return array(
|
168 |
+
'company', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
|
169 |
+
'countryName', 'customerId', 'extendedAddress', 'firstName',
|
170 |
+
'lastName', 'locality', 'postalCode', 'region', 'streetAddress'
|
171 |
+
);
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* creates a full array signature of a valid update request
|
176 |
+
* @return array gateway update request format
|
177 |
+
*/
|
178 |
+
public static function updateSignature()
|
179 |
+
{
|
180 |
+
// TODO: remove customerId from update signature
|
181 |
+
return self::createSignature();
|
182 |
+
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* verifies that a valid address id is being used
|
187 |
+
* @ignore
|
188 |
+
* @param string $id address id
|
189 |
+
* @throws InvalidArgumentException
|
190 |
+
*/
|
191 |
+
private function _validateId($id = null)
|
192 |
+
{
|
193 |
+
if (empty($id) || trim($id) == "") {
|
194 |
+
throw new InvalidArgumentException(
|
195 |
+
'expected address id to be set'
|
196 |
+
);
|
197 |
+
}
|
198 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
|
199 |
+
throw new InvalidArgumentException(
|
200 |
+
$id . ' is an invalid address id.'
|
201 |
+
);
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* verifies that a valid customer id is being used
|
207 |
+
* @ignore
|
208 |
+
* @param string $id customer id
|
209 |
+
* @throws InvalidArgumentException
|
210 |
+
*/
|
211 |
+
private function _validateCustomerId($id = null)
|
212 |
+
{
|
213 |
+
if (empty($id) || trim($id) == "") {
|
214 |
+
throw new InvalidArgumentException(
|
215 |
+
'expected customer id to be set'
|
216 |
+
);
|
217 |
+
}
|
218 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
|
219 |
+
throw new InvalidArgumentException(
|
220 |
+
$id . ' is an invalid customer id.'
|
221 |
+
);
|
222 |
+
}
|
223 |
+
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* determines if a string id or Customer object was passed
|
228 |
+
* @ignore
|
229 |
+
* @param mixed $customerOrId
|
230 |
+
* @return string customerId
|
231 |
+
*/
|
232 |
+
private function _determineCustomerId($customerOrId)
|
233 |
+
{
|
234 |
+
$customerId = ($customerOrId instanceof Braintree_Customer) ? $customerOrId->id : $customerOrId;
|
235 |
+
$this->_validateCustomerId($customerId);
|
236 |
+
return $customerId;
|
237 |
+
|
238 |
+
}
|
239 |
+
|
240 |
+
/* private class methods */
|
241 |
+
/**
|
242 |
+
* sends the create request to the gateway
|
243 |
+
* @ignore
|
244 |
+
* @param string $subPath
|
245 |
+
* @param array $params
|
246 |
+
* @return mixed
|
247 |
+
*/
|
248 |
+
private function _doCreate($subPath, $params)
|
249 |
+
{
|
250 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
251 |
+
$response = $this->_http->post($fullPath, $params);
|
252 |
+
|
253 |
+
return $this->_verifyGatewayResponse($response);
|
254 |
+
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* generic method for validating incoming gateway responses
|
259 |
+
*
|
260 |
+
* creates a new Braintree_Address object and encapsulates
|
261 |
+
* it inside a Braintree_Result_Successful object, or
|
262 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
263 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
264 |
+
*
|
265 |
+
* @ignore
|
266 |
+
* @param array $response gateway response values
|
267 |
+
* @return object Result_Successful or Result_Error
|
268 |
+
* @throws Braintree_Exception_Unexpected
|
269 |
+
*/
|
270 |
+
private function _verifyGatewayResponse($response)
|
271 |
+
{
|
272 |
+
if (isset($response['address'])) {
|
273 |
+
// return a populated instance of Braintree_Address
|
274 |
+
return new Braintree_Result_Successful(
|
275 |
+
Braintree_Address::factory($response['address'])
|
276 |
+
);
|
277 |
+
} else if (isset($response['apiErrorResponse'])) {
|
278 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
279 |
+
} else {
|
280 |
+
throw new Braintree_Exception_Unexpected(
|
281 |
+
"Expected address or apiErrorResponse"
|
282 |
+
);
|
283 |
+
}
|
284 |
+
|
285 |
+
}
|
286 |
+
}
|
lib/Braintree/ApplePayCard.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree ApplePayCard module
|
4 |
+
* Creates and manages Braintree Apple Pay cards
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* See {@link https://developers.braintreepayments.com/javascript+php}<br />
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @category Resources
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*
|
14 |
+
* @property-read string $cardType
|
15 |
+
* @property-read string $createdAt
|
16 |
+
* @property-read string $expirationDate
|
17 |
+
* @property-read string $expirationMonth
|
18 |
+
* @property-read string $expirationYear
|
19 |
+
* @property-read string $imageUrl
|
20 |
+
* @property-read string $last4
|
21 |
+
* @property-read string $token
|
22 |
+
* @property-read string $paymentInstrumentName
|
23 |
+
* @property-read string $updatedAt
|
24 |
+
*/
|
25 |
+
class Braintree_ApplePayCard extends Braintree
|
26 |
+
{
|
27 |
+
// Card Type
|
28 |
+
const AMEX = 'Apple Pay - American Express';
|
29 |
+
const MASTER_CARD = 'Apple Pay - MasterCard';
|
30 |
+
const VISA = 'Apple Pay - Visa';
|
31 |
+
|
32 |
+
/* instance methods */
|
33 |
+
/**
|
34 |
+
* returns false if default is null or false
|
35 |
+
*
|
36 |
+
* @return boolean
|
37 |
+
*/
|
38 |
+
public function isDefault()
|
39 |
+
{
|
40 |
+
return $this->default;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* checks whether the card is expired based on the current date
|
45 |
+
*
|
46 |
+
* @return boolean
|
47 |
+
*/
|
48 |
+
public function isExpired()
|
49 |
+
{
|
50 |
+
return $this->expired;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* factory method: returns an instance of Braintree_ApplePayCard
|
55 |
+
* to the requesting method, with populated properties
|
56 |
+
*
|
57 |
+
* @ignore
|
58 |
+
* @return object instance of Braintree_ApplePayCard
|
59 |
+
*/
|
60 |
+
public static function factory($attributes)
|
61 |
+
{
|
62 |
+
$defaultAttributes = array(
|
63 |
+
'expirationMonth' => '',
|
64 |
+
'expirationYear' => '',
|
65 |
+
'last4' => '',
|
66 |
+
);
|
67 |
+
|
68 |
+
$instance = new self();
|
69 |
+
$instance->_initialize(array_merge($defaultAttributes, $attributes));
|
70 |
+
return $instance;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* sets instance properties from an array of values
|
75 |
+
*
|
76 |
+
* @access protected
|
77 |
+
* @param array $applePayCardAttribs array of Apple Pay card properties
|
78 |
+
* @return none
|
79 |
+
*/
|
80 |
+
protected function _initialize($applePayCardAttribs)
|
81 |
+
{
|
82 |
+
// set the attributes
|
83 |
+
$this->_attributes = $applePayCardAttribs;
|
84 |
+
|
85 |
+
$subscriptionArray = array();
|
86 |
+
if (isset($applePayCardAttribs['subscriptions'])) {
|
87 |
+
foreach ($applePayCardAttribs['subscriptions'] AS $subscription) {
|
88 |
+
$subscriptionArray[] = Braintree_Subscription::factory($subscription);
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
$this->_set('subscriptions', $subscriptionArray);
|
93 |
+
$this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear);
|
94 |
+
}
|
95 |
+
}
|
lib/Braintree/ClientToken.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_ClientToken
|
4 |
+
{
|
5 |
+
const DEFAULT_VERSION = 2;
|
6 |
+
|
7 |
+
|
8 |
+
// static methods redirecting to gateway
|
9 |
+
|
10 |
+
public static function generate($params=array())
|
11 |
+
{
|
12 |
+
return Braintree_Configuration::gateway()->clientToken()->generate($params);
|
13 |
+
}
|
14 |
+
|
15 |
+
public static function conditionallyVerifyKeys($params)
|
16 |
+
{
|
17 |
+
return Braintree_Configuration::gateway()->clientToken()->conditionallyVerifyKeys($params);
|
18 |
+
}
|
19 |
+
|
20 |
+
public static function generateWithCustomerIdSignature()
|
21 |
+
{
|
22 |
+
return Braintree_Configuration::gateway()->clientToken()->generateWithCustomerIdSignature();
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function generateWithoutCustomerIdSignature()
|
26 |
+
{
|
27 |
+
return Braintree_Configuration::gateway()->clientToken()->generateWithoutCustomerIdSignature();
|
28 |
+
}
|
29 |
+
}
|
lib/Braintree/ClientTokenGateway.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_ClientTokenGateway
|
4 |
+
{
|
5 |
+
private $_gateway;
|
6 |
+
private $_config;
|
7 |
+
private $_http;
|
8 |
+
|
9 |
+
public function __construct($gateway)
|
10 |
+
{
|
11 |
+
$this->_gateway = $gateway;
|
12 |
+
$this->_config = $gateway->config;
|
13 |
+
$this->_http = new Braintree_Http($gateway->config);
|
14 |
+
}
|
15 |
+
|
16 |
+
public function generate($params=array())
|
17 |
+
{
|
18 |
+
if (!array_key_exists("version", $params)) {
|
19 |
+
$params["version"] = Braintree_ClientToken::DEFAULT_VERSION;
|
20 |
+
}
|
21 |
+
|
22 |
+
$this->conditionallyVerifyKeys($params);
|
23 |
+
$generateParams = array("client_token" => $params);
|
24 |
+
|
25 |
+
return $this->_doGenerate('/client_token', $generateParams);
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* sends the generate request to the gateway
|
30 |
+
*
|
31 |
+
* @ignore
|
32 |
+
* @param var $url
|
33 |
+
* @param array $params
|
34 |
+
* @return mixed
|
35 |
+
*/
|
36 |
+
public function _doGenerate($subPath, $params)
|
37 |
+
{
|
38 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
39 |
+
$response = $this->_http->post($fullPath, $params);
|
40 |
+
|
41 |
+
return $this->_verifyGatewayResponse($response);
|
42 |
+
}
|
43 |
+
|
44 |
+
public function conditionallyVerifyKeys($params)
|
45 |
+
{
|
46 |
+
if (array_key_exists("customerId", $params)) {
|
47 |
+
Braintree_Util::verifyKeys($this->generateWithCustomerIdSignature(), $params);
|
48 |
+
} else {
|
49 |
+
Braintree_Util::verifyKeys($this->generateWithoutCustomerIdSignature(), $params);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
public function generateWithCustomerIdSignature()
|
54 |
+
{
|
55 |
+
return array("version", "customerId", "proxyMerchantId", array("options" => array("makeDefault", "verifyCard", "failOnDuplicatePaymentMethod")), "merchantAccountId");
|
56 |
+
}
|
57 |
+
|
58 |
+
public function generateWithoutCustomerIdSignature()
|
59 |
+
{
|
60 |
+
return array("version", "proxyMerchantId", "merchantAccountId");
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* generic method for validating incoming gateway responses
|
65 |
+
*
|
66 |
+
* If the request is successful, returns a client token string.
|
67 |
+
* Otherwise, throws an InvalidArgumentException with the error
|
68 |
+
* response from the Gateway or an HTTP status code exception.
|
69 |
+
*
|
70 |
+
* @ignore
|
71 |
+
* @param array $response gateway response values
|
72 |
+
* @return string client token
|
73 |
+
* @throws InvalidArgumentException | HTTP status code exception
|
74 |
+
*/
|
75 |
+
private function _verifyGatewayResponse($response)
|
76 |
+
{
|
77 |
+
if (isset($response['clientToken'])) {
|
78 |
+
return $response['clientToken']['value'];
|
79 |
+
} elseif (isset($response['apiErrorResponse'])) {
|
80 |
+
throw new InvalidArgumentException(
|
81 |
+
$response['apiErrorResponse']['message']
|
82 |
+
);
|
83 |
+
} else {
|
84 |
+
throw new Braintree_Exception_Unexpected(
|
85 |
+
"Expected clientToken or apiErrorResponse"
|
86 |
+
);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
lib/Braintree/CoinbaseAccount.php
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree CoinbaseAccount module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Manages Braintree CoinbaseAccounts
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
* @property-read string $token
|
21 |
+
* @property-read string $userId
|
22 |
+
* @property-read string $userName
|
23 |
+
* @property-read string $userEmail
|
24 |
+
*/
|
25 |
+
class Braintree_CoinbaseAccount extends Braintree
|
26 |
+
{
|
27 |
+
/**
|
28 |
+
* factory method: returns an instance of Braintree_CoinbaseAccount
|
29 |
+
* to the requesting method, with populated properties
|
30 |
+
*
|
31 |
+
* @ignore
|
32 |
+
* @return object instance of Braintree_CoinbaseAccount
|
33 |
+
*/
|
34 |
+
public static function factory($attributes)
|
35 |
+
{
|
36 |
+
$instance = new self();
|
37 |
+
$instance->_initialize($attributes);
|
38 |
+
return $instance;
|
39 |
+
}
|
40 |
+
|
41 |
+
/* instance methods */
|
42 |
+
|
43 |
+
/**
|
44 |
+
* returns false if default is null or false
|
45 |
+
*
|
46 |
+
* @return boolean
|
47 |
+
*/
|
48 |
+
public function isDefault()
|
49 |
+
{
|
50 |
+
return $this->default;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* sets instance properties from an array of values
|
55 |
+
*
|
56 |
+
* @access protected
|
57 |
+
* @param array $coinbaseAccountAttribs array of coinbaseAccount data
|
58 |
+
* @return none
|
59 |
+
*/
|
60 |
+
protected function _initialize($coinbaseAccountAttribs)
|
61 |
+
{
|
62 |
+
// set the attributes
|
63 |
+
$this->_attributes = $coinbaseAccountAttribs;
|
64 |
+
|
65 |
+
$subscriptionArray = array();
|
66 |
+
if (isset($coinbaseAccountAttribs['subscriptions'])) {
|
67 |
+
foreach ($coinbaseAccountAttribs['subscriptions'] AS $subscription) {
|
68 |
+
$subscriptionArray[] = Braintree_Subscription::factory($subscription);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
$this->_set('subscriptions', $subscriptionArray);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* create a printable representation of the object as:
|
77 |
+
* ClassName[property=value, property=value]
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function __toString()
|
81 |
+
{
|
82 |
+
return __CLASS__ . '[' .
|
83 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// static methods redirecting to gateway
|
88 |
+
|
89 |
+
public static function find($token)
|
90 |
+
{
|
91 |
+
return Braintree_Configuration::gateway()->coinbaseAccount()->find($token);
|
92 |
+
}
|
93 |
+
|
94 |
+
public static function update($token, $attributes)
|
95 |
+
{
|
96 |
+
return Braintree_Configuration::gateway()->coinbaseAccount()->update($token, $attributes);
|
97 |
+
}
|
98 |
+
|
99 |
+
public static function delete($token)
|
100 |
+
{
|
101 |
+
return Braintree_Configuration::gateway()->coinbaseAccount()->delete($token);
|
102 |
+
}
|
103 |
+
|
104 |
+
public static function sale($token, $transactionAttribs)
|
105 |
+
{
|
106 |
+
return Braintree_Configuration::gateway()->coinbaseAccount()->sale($token, $transactionAttribs);
|
107 |
+
}
|
108 |
+
}
|
lib/Braintree/Collection.php
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Generic collection
|
4 |
+
*
|
5 |
+
* PHP Version 5
|
6 |
+
*
|
7 |
+
* Based on Generic Collection class from:
|
8 |
+
* {@link http://codeutopia.net/code/library/CU/Collection.php}
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @subpackage Utility
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Braintree_Collection implements Countable, IteratorAggregate, ArrayAccess
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
*
|
19 |
+
* @var array $_collection collection storage
|
20 |
+
*/
|
21 |
+
protected $_collection = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Add a value into the collection
|
25 |
+
* @param string $value
|
26 |
+
*/
|
27 |
+
public function add($value)
|
28 |
+
{
|
29 |
+
$this->_collection[] = $value;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Set index's value
|
34 |
+
* @param integer $index
|
35 |
+
* @param mixed $value
|
36 |
+
* @throws OutOfRangeException
|
37 |
+
*/
|
38 |
+
public function set($index, $value)
|
39 |
+
{
|
40 |
+
if($index >= $this->count())
|
41 |
+
throw new OutOfRangeException('Index out of range');
|
42 |
+
|
43 |
+
$this->_collection[$index] = $value;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Remove a value from the collection
|
48 |
+
* @param integer $index index to remove
|
49 |
+
* @throws OutOfRangeException if index is out of range
|
50 |
+
*/
|
51 |
+
public function remove($index)
|
52 |
+
{
|
53 |
+
if($index >= $this->count())
|
54 |
+
throw new OutOfRangeException('Index out of range');
|
55 |
+
|
56 |
+
array_splice($this->_collection, $index, 1);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Return value at index
|
61 |
+
* @param integer $index
|
62 |
+
* @return mixed
|
63 |
+
* @throws OutOfRangeException
|
64 |
+
*/
|
65 |
+
public function get($index)
|
66 |
+
{
|
67 |
+
if($index >= $this->count())
|
68 |
+
throw new OutOfRangeException('Index out of range');
|
69 |
+
|
70 |
+
return $this->_collection[$index];
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Determine if index exists
|
75 |
+
* @param integer $index
|
76 |
+
* @return boolean
|
77 |
+
*/
|
78 |
+
public function exists($index)
|
79 |
+
{
|
80 |
+
if($index >= $this->count())
|
81 |
+
return false;
|
82 |
+
|
83 |
+
return true;
|
84 |
+
}
|
85 |
+
/**
|
86 |
+
* Return count of items in collection
|
87 |
+
* Implements countable
|
88 |
+
* @return integer
|
89 |
+
*/
|
90 |
+
public function count()
|
91 |
+
{
|
92 |
+
return count($this->_collection);
|
93 |
+
}
|
94 |
+
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Return an iterator
|
98 |
+
* Implements IteratorAggregate
|
99 |
+
* @return ArrayIterator
|
100 |
+
*/
|
101 |
+
public function getIterator()
|
102 |
+
{
|
103 |
+
return new ArrayIterator($this->_collection);
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Set offset to value
|
108 |
+
* Implements ArrayAccess
|
109 |
+
* @see set
|
110 |
+
* @param integer $offset
|
111 |
+
* @param mixed $value
|
112 |
+
*/
|
113 |
+
public function offsetSet($offset, $value)
|
114 |
+
{
|
115 |
+
$this->set($offset, $value);
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Unset offset
|
120 |
+
* Implements ArrayAccess
|
121 |
+
* @see remove
|
122 |
+
* @param integer $offset
|
123 |
+
*/
|
124 |
+
public function offsetUnset($offset)
|
125 |
+
{
|
126 |
+
$this->remove($offset);
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* get an offset's value
|
131 |
+
* Implements ArrayAccess
|
132 |
+
* @see get
|
133 |
+
* @param integer $offset
|
134 |
+
* @return mixed
|
135 |
+
*/
|
136 |
+
public function offsetGet($offset)
|
137 |
+
{
|
138 |
+
return $this->get($offset);
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Determine if offset exists
|
143 |
+
* Implements ArrayAccess
|
144 |
+
* @see exists
|
145 |
+
* @param integer $offset
|
146 |
+
* @return boolean
|
147 |
+
*/
|
148 |
+
public function offsetExists($offset)
|
149 |
+
{
|
150 |
+
return $this->exists($offset);
|
151 |
+
}
|
152 |
+
|
153 |
+
}
|
lib/Braintree/Configuration.php
ADDED
@@ -0,0 +1,329 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* Configuration registry
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Utility
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class Braintree_Configuration
|
12 |
+
{
|
13 |
+
public static $global;
|
14 |
+
|
15 |
+
private $_environment = null;
|
16 |
+
private $_merchantId = null;
|
17 |
+
private $_publicKey = null;
|
18 |
+
private $_privateKey = null;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Braintree API version to use
|
22 |
+
* @access public
|
23 |
+
*/
|
24 |
+
const API_VERSION = 4;
|
25 |
+
|
26 |
+
public function __construct($attribs = array())
|
27 |
+
{
|
28 |
+
foreach ($attribs as $kind => $value) {
|
29 |
+
if ($kind == 'environment') {
|
30 |
+
$this->setEnvironment($value);
|
31 |
+
}
|
32 |
+
if ($kind == 'merchantId') {
|
33 |
+
$this->setMerchantId($value);
|
34 |
+
}
|
35 |
+
if ($kind == 'publicKey') {
|
36 |
+
$this->setPublicKey($value);
|
37 |
+
}
|
38 |
+
if ($kind == 'privateKey') {
|
39 |
+
$this->setPrivateKey($value);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* resets configuration to default
|
46 |
+
* @access public
|
47 |
+
*/
|
48 |
+
public static function reset()
|
49 |
+
{
|
50 |
+
self::$global = new Braintree_Configuration();
|
51 |
+
}
|
52 |
+
|
53 |
+
public static function gateway()
|
54 |
+
{
|
55 |
+
return new Braintree_Gateway(self::$global);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
*
|
60 |
+
* @access protected
|
61 |
+
* @static
|
62 |
+
* @var array valid environments, used for validation
|
63 |
+
*/
|
64 |
+
private static $_validEnvironments = array(
|
65 |
+
'development',
|
66 |
+
'sandbox',
|
67 |
+
'production',
|
68 |
+
'qa',
|
69 |
+
);
|
70 |
+
|
71 |
+
/**
|
72 |
+
* resets configuration to default
|
73 |
+
* @access public
|
74 |
+
* @static
|
75 |
+
*/
|
76 |
+
public static function environment($value=null)
|
77 |
+
{
|
78 |
+
if (empty($value)) {
|
79 |
+
return self::$global->getEnvironment();
|
80 |
+
}
|
81 |
+
self::$global->setEnvironment($value);
|
82 |
+
}
|
83 |
+
|
84 |
+
public static function merchantId($value=null)
|
85 |
+
{
|
86 |
+
if (empty($value)) {
|
87 |
+
return self::$global->getMerchantId();
|
88 |
+
}
|
89 |
+
self::$global->setMerchantId($value);
|
90 |
+
}
|
91 |
+
|
92 |
+
public static function publicKey($value=null)
|
93 |
+
{
|
94 |
+
if (empty($value)) {
|
95 |
+
return self::$global->getPublicKey();
|
96 |
+
}
|
97 |
+
self::$global->setPublicKey($value);
|
98 |
+
}
|
99 |
+
|
100 |
+
public static function privateKey($value=null)
|
101 |
+
{
|
102 |
+
if (empty($value)) {
|
103 |
+
return self::$global->getPrivateKey();
|
104 |
+
}
|
105 |
+
self::$global->setPrivateKey($value);
|
106 |
+
}
|
107 |
+
|
108 |
+
public function assertValid()
|
109 |
+
{
|
110 |
+
if (empty($this->_environment)) {
|
111 |
+
throw new Braintree_Exception_Configuration('environment needs to be set.');
|
112 |
+
} else if (empty($this->_merchantId)) {
|
113 |
+
throw new Braintree_Exception_Configuration('merchantId needs to be set.');
|
114 |
+
} else if (empty($this->_publicKey)) {
|
115 |
+
throw new Braintree_Exception_Configuration('publicKey needs to be set.');
|
116 |
+
} else if (empty($this->_privateKey)) {
|
117 |
+
throw new Braintree_Exception_Configuration('privateKey needs to be set.');
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
|
122 |
+
public function getEnvironment()
|
123 |
+
{
|
124 |
+
return $this->_environment;
|
125 |
+
}
|
126 |
+
|
127 |
+
public function setEnvironment($value)
|
128 |
+
{
|
129 |
+
if (!in_array($value, self::$_validEnvironments)) {
|
130 |
+
throw new Braintree_Exception_Configuration('"' .
|
131 |
+
$value . '" is not a valid environment.');
|
132 |
+
}
|
133 |
+
$this->_environment = $value;
|
134 |
+
}
|
135 |
+
|
136 |
+
public function getMerchantId()
|
137 |
+
{
|
138 |
+
return $this->_merchantId;
|
139 |
+
}
|
140 |
+
|
141 |
+
public function setMerchantId($value)
|
142 |
+
{
|
143 |
+
$this->_merchantId = $value;
|
144 |
+
}
|
145 |
+
|
146 |
+
public function getPublicKey()
|
147 |
+
{
|
148 |
+
return $this->_publicKey;
|
149 |
+
}
|
150 |
+
|
151 |
+
public function setPublicKey($value)
|
152 |
+
{
|
153 |
+
$this->_publicKey = $value;
|
154 |
+
}
|
155 |
+
|
156 |
+
public function getPrivateKey()
|
157 |
+
{
|
158 |
+
return $this->_privateKey;
|
159 |
+
}
|
160 |
+
|
161 |
+
public function setPrivateKey($value)
|
162 |
+
{
|
163 |
+
$this->_privateKey = $value;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* returns the base braintree gateway URL based on config values
|
168 |
+
*
|
169 |
+
* @access public
|
170 |
+
* @param none
|
171 |
+
* @return string braintree gateway URL
|
172 |
+
*/
|
173 |
+
public function baseUrl()
|
174 |
+
{
|
175 |
+
return $this->protocol() . '://' .
|
176 |
+
$this->serverName() . ':' .
|
177 |
+
$this->portNumber();
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* sets the merchant path based on merchant ID
|
182 |
+
*
|
183 |
+
* @access protected
|
184 |
+
* @param none
|
185 |
+
* @return string merchant path uri
|
186 |
+
*/
|
187 |
+
public function merchantPath()
|
188 |
+
{
|
189 |
+
return '/merchants/'.$this->_merchantId;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* sets the physical path for the location of the CA certs
|
194 |
+
*
|
195 |
+
* @access public
|
196 |
+
* @param none
|
197 |
+
* @return string filepath
|
198 |
+
*/
|
199 |
+
public function caFile($sslPath = NULL)
|
200 |
+
{
|
201 |
+
$sslPath = $sslPath ? $sslPath : DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR .
|
202 |
+
'ssl' . DIRECTORY_SEPARATOR;
|
203 |
+
|
204 |
+
$caPath = realpath(
|
205 |
+
dirname(__FILE__) .
|
206 |
+
$sslPath . 'api_braintreegateway_com.ca.crt'
|
207 |
+
);
|
208 |
+
|
209 |
+
if (!file_exists($caPath))
|
210 |
+
{
|
211 |
+
throw new Braintree_Exception_SSLCaFileNotFound();
|
212 |
+
}
|
213 |
+
|
214 |
+
return $caPath;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* returns the port number depending on environment
|
219 |
+
*
|
220 |
+
* @access public
|
221 |
+
* @param none
|
222 |
+
* @return int portnumber
|
223 |
+
*/
|
224 |
+
public function portNumber()
|
225 |
+
{
|
226 |
+
if ($this->sslOn()) {
|
227 |
+
return 443;
|
228 |
+
}
|
229 |
+
return getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* returns http protocol depending on environment
|
234 |
+
*
|
235 |
+
* @access public
|
236 |
+
* @param none
|
237 |
+
* @return string http || https
|
238 |
+
*/
|
239 |
+
public function protocol()
|
240 |
+
{
|
241 |
+
return $this->sslOn() ? 'https' : 'http';
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* returns gateway server name depending on environment
|
246 |
+
*
|
247 |
+
* @access public
|
248 |
+
* @param none
|
249 |
+
* @return string server domain name
|
250 |
+
*/
|
251 |
+
public function serverName()
|
252 |
+
{
|
253 |
+
switch($this->_environment) {
|
254 |
+
case 'production':
|
255 |
+
$serverName = 'api.braintreegateway.com';
|
256 |
+
break;
|
257 |
+
case 'qa':
|
258 |
+
$serverName = 'gateway.qa.braintreepayments.com';
|
259 |
+
break;
|
260 |
+
case 'sandbox':
|
261 |
+
$serverName = 'api.sandbox.braintreegateway.com';
|
262 |
+
break;
|
263 |
+
case 'development':
|
264 |
+
default:
|
265 |
+
$serverName = 'localhost';
|
266 |
+
break;
|
267 |
+
}
|
268 |
+
|
269 |
+
return $serverName;
|
270 |
+
}
|
271 |
+
|
272 |
+
public function authUrl()
|
273 |
+
{
|
274 |
+
switch($this->_environment) {
|
275 |
+
case 'production':
|
276 |
+
$serverName = 'https://auth.venmo.com';
|
277 |
+
break;
|
278 |
+
case 'qa':
|
279 |
+
$serverName = 'https://auth.qa.venmo.com';
|
280 |
+
break;
|
281 |
+
case 'sandbox':
|
282 |
+
$serverName = 'https://auth.sandbox.venmo.com';
|
283 |
+
break;
|
284 |
+
case 'development':
|
285 |
+
default:
|
286 |
+
$serverName = 'http://auth.venmo.dev:9292';
|
287 |
+
break;
|
288 |
+
}
|
289 |
+
|
290 |
+
return $serverName;
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* returns boolean indicating SSL is on or off for this session,
|
295 |
+
* depending on environment
|
296 |
+
*
|
297 |
+
* @access public
|
298 |
+
* @param none
|
299 |
+
* @return boolean
|
300 |
+
*/
|
301 |
+
public function sslOn()
|
302 |
+
{
|
303 |
+
switch($this->_environment) {
|
304 |
+
case 'development':
|
305 |
+
$ssl = false;
|
306 |
+
break;
|
307 |
+
case 'production':
|
308 |
+
case 'qa':
|
309 |
+
case 'sandbox':
|
310 |
+
default:
|
311 |
+
$ssl = true;
|
312 |
+
break;
|
313 |
+
}
|
314 |
+
|
315 |
+
return $ssl;
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* log message to default logger
|
320 |
+
*
|
321 |
+
* @param string $message
|
322 |
+
*
|
323 |
+
*/
|
324 |
+
public function logMessage($message)
|
325 |
+
{
|
326 |
+
error_log('[Braintree] ' . $message);
|
327 |
+
}
|
328 |
+
}
|
329 |
+
Braintree_Configuration::reset();
|
lib/Braintree/CreditCard.php
ADDED
@@ -0,0 +1,292 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree CreditCard module
|
4 |
+
* Creates and manages Braintree CreditCards
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* For more detailed information on CreditCards, see {@link http://www.braintreepayments.com/gateway/credit-card-api http://www.braintreepaymentsolutions.com/gateway/credit-card-api}<br />
|
9 |
+
* 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}
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @category Resources
|
13 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
14 |
+
*
|
15 |
+
* @property-read string $billingAddress
|
16 |
+
* @property-read string $bin
|
17 |
+
* @property-read string $cardType
|
18 |
+
* @property-read string $cardholderName
|
19 |
+
* @property-read string $createdAt
|
20 |
+
* @property-read string $customerId
|
21 |
+
* @property-read string $expirationDate
|
22 |
+
* @property-read string $expirationMonth
|
23 |
+
* @property-read string $expirationYear
|
24 |
+
* @property-read string $imageUrl
|
25 |
+
* @property-read string $last4
|
26 |
+
* @property-read string $maskedNumber
|
27 |
+
* @property-read string $token
|
28 |
+
* @property-read string $updatedAt
|
29 |
+
*/
|
30 |
+
class Braintree_CreditCard extends Braintree
|
31 |
+
{
|
32 |
+
// Card Type
|
33 |
+
const AMEX = 'American Express';
|
34 |
+
const CARTE_BLANCHE = 'Carte Blanche';
|
35 |
+
const CHINA_UNION_PAY = 'China UnionPay';
|
36 |
+
const DINERS_CLUB_INTERNATIONAL = 'Diners Club';
|
37 |
+
const DISCOVER = 'Discover';
|
38 |
+
const JCB = 'JCB';
|
39 |
+
const LASER = 'Laser';
|
40 |
+
const MAESTRO = 'Maestro';
|
41 |
+
const MASTER_CARD = 'MasterCard';
|
42 |
+
const SOLO = 'Solo';
|
43 |
+
const SWITCH_TYPE = 'Switch';
|
44 |
+
const VISA = 'Visa';
|
45 |
+
const UNKNOWN = 'Unknown';
|
46 |
+
|
47 |
+
// Credit card origination location
|
48 |
+
const INTERNATIONAL = "international";
|
49 |
+
const US = "us";
|
50 |
+
|
51 |
+
const PREPAID_YES = 'Yes';
|
52 |
+
const PREPAID_NO = 'No';
|
53 |
+
const PREPAID_UNKNOWN = 'Unknown';
|
54 |
+
|
55 |
+
const PAYROLL_YES = 'Yes';
|
56 |
+
const PAYROLL_NO = 'No';
|
57 |
+
const PAYROLL_UNKNOWN = 'Unknown';
|
58 |
+
|
59 |
+
const HEALTHCARE_YES = 'Yes';
|
60 |
+
const HEALTHCARE_NO = 'No';
|
61 |
+
const HEALTHCARE_UNKNOWN = 'Unknown';
|
62 |
+
|
63 |
+
const DURBIN_REGULATED_YES = 'Yes';
|
64 |
+
const DURBIN_REGULATED_NO = 'No';
|
65 |
+
const DURBIN_REGULATED_UNKNOWN = 'Unknown';
|
66 |
+
|
67 |
+
const DEBIT_YES = 'Yes';
|
68 |
+
const DEBIT_NO = 'No';
|
69 |
+
const DEBIT_UNKNOWN = 'Unknown';
|
70 |
+
|
71 |
+
const COMMERCIAL_YES = 'Yes';
|
72 |
+
const COMMERCIAL_NO = 'No';
|
73 |
+
const COMMERCIAL_UNKNOWN = 'Unknown';
|
74 |
+
|
75 |
+
const COUNTRY_OF_ISSUANCE_UNKNOWN = "Unknown";
|
76 |
+
const ISSUING_BANK_UNKNOWN = "Unknown";
|
77 |
+
|
78 |
+
/* instance methods */
|
79 |
+
/**
|
80 |
+
* returns false if default is null or false
|
81 |
+
*
|
82 |
+
* @return boolean
|
83 |
+
*/
|
84 |
+
public function isDefault()
|
85 |
+
{
|
86 |
+
return $this->default;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* checks whether the card is expired based on the current date
|
91 |
+
*
|
92 |
+
* @return boolean
|
93 |
+
*/
|
94 |
+
public function isExpired()
|
95 |
+
{
|
96 |
+
return $this->expired;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* checks whether the card is associated with venmo sdk
|
101 |
+
*
|
102 |
+
* @return boolean
|
103 |
+
*/
|
104 |
+
public function isVenmoSdk()
|
105 |
+
{
|
106 |
+
return $this->venmoSdk;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* sets instance properties from an array of values
|
111 |
+
*
|
112 |
+
* @access protected
|
113 |
+
* @param array $creditCardAttribs array of creditcard data
|
114 |
+
* @return none
|
115 |
+
*/
|
116 |
+
protected function _initialize($creditCardAttribs)
|
117 |
+
{
|
118 |
+
// set the attributes
|
119 |
+
$this->_attributes = $creditCardAttribs;
|
120 |
+
|
121 |
+
// map each address into its own object
|
122 |
+
$billingAddress = isset($creditCardAttribs['billingAddress']) ?
|
123 |
+
Braintree_Address::factory($creditCardAttribs['billingAddress']) :
|
124 |
+
null;
|
125 |
+
|
126 |
+
$subscriptionArray = array();
|
127 |
+
if (isset($creditCardAttribs['subscriptions'])) {
|
128 |
+
foreach ($creditCardAttribs['subscriptions'] AS $subscription) {
|
129 |
+
$subscriptionArray[] = Braintree_Subscription::factory($subscription);
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
$this->_set('subscriptions', $subscriptionArray);
|
134 |
+
$this->_set('billingAddress', $billingAddress);
|
135 |
+
$this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear);
|
136 |
+
$this->_set('maskedNumber', $this->bin . '******' . $this->last4);
|
137 |
+
|
138 |
+
if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) {
|
139 |
+
$verifications = $creditCardAttribs['verifications'];
|
140 |
+
usort($verifications, array($this, '_compareCreatedAtOnVerifications'));
|
141 |
+
|
142 |
+
$this->_set('verification', Braintree_CreditCardVerification::factory($verifications[0]));
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
private function _compareCreatedAtOnVerifications($verificationAttrib1, $verificationAttrib2)
|
147 |
+
{
|
148 |
+
return ($verificationAttrib2['createdAt'] < $verificationAttrib1['createdAt']) ? -1 : 1;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* returns false if comparing object is not a Braintree_CreditCard,
|
153 |
+
* or is a Braintree_CreditCard with a different id
|
154 |
+
*
|
155 |
+
* @param object $otherCreditCard customer to compare against
|
156 |
+
* @return boolean
|
157 |
+
*/
|
158 |
+
public function isEqual($otherCreditCard)
|
159 |
+
{
|
160 |
+
return !($otherCreditCard instanceof Braintree_CreditCard) ? false : $this->token === $otherCreditCard->token;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* create a printable representation of the object as:
|
165 |
+
* ClassName[property=value, property=value]
|
166 |
+
* @return string
|
167 |
+
*/
|
168 |
+
public function __toString()
|
169 |
+
{
|
170 |
+
return __CLASS__ . '[' .
|
171 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* factory method: returns an instance of Braintree_CreditCard
|
176 |
+
* to the requesting method, with populated properties
|
177 |
+
*
|
178 |
+
* @ignore
|
179 |
+
* @return object instance of Braintree_CreditCard
|
180 |
+
*/
|
181 |
+
public static function factory($attributes)
|
182 |
+
{
|
183 |
+
$defaultAttributes = array(
|
184 |
+
'bin' => '',
|
185 |
+
'expirationMonth' => '',
|
186 |
+
'expirationYear' => '',
|
187 |
+
'last4' => '',
|
188 |
+
);
|
189 |
+
|
190 |
+
$instance = new self();
|
191 |
+
$instance->_initialize(array_merge($defaultAttributes, $attributes));
|
192 |
+
return $instance;
|
193 |
+
}
|
194 |
+
|
195 |
+
|
196 |
+
// static methods redirecting to gateway
|
197 |
+
|
198 |
+
public static function create($attribs)
|
199 |
+
{
|
200 |
+
return Braintree_Configuration::gateway()->creditCard()->create($attribs);
|
201 |
+
}
|
202 |
+
|
203 |
+
public static function createNoValidate($attribs)
|
204 |
+
{
|
205 |
+
return Braintree_Configuration::gateway()->creditCard()->createNoValidate($attribs);
|
206 |
+
}
|
207 |
+
|
208 |
+
public static function createFromTransparentRedirect($queryString)
|
209 |
+
{
|
210 |
+
return Braintree_Configuration::gateway()->creditCard()->createFromTransparentRedirect($queryString);
|
211 |
+
}
|
212 |
+
|
213 |
+
public static function createCreditCardUrl()
|
214 |
+
{
|
215 |
+
return Braintree_Configuration::gateway()->creditCard()->createCreditCardUrl();
|
216 |
+
}
|
217 |
+
|
218 |
+
public static function expired()
|
219 |
+
{
|
220 |
+
return Braintree_Configuration::gateway()->creditCard()->expired();
|
221 |
+
}
|
222 |
+
|
223 |
+
public static function fetchExpired($ids)
|
224 |
+
{
|
225 |
+
return Braintree_Configuration::gateway()->creditCard()->fetchExpired($ids);
|
226 |
+
}
|
227 |
+
|
228 |
+
public static function expiringBetween($startDate, $endDate)
|
229 |
+
{
|
230 |
+
return Braintree_Configuration::gateway()->creditCard()->expiringBetween($startDate, $endDate);
|
231 |
+
}
|
232 |
+
|
233 |
+
public static function fetchExpiring($startDate, $endDate, $ids)
|
234 |
+
{
|
235 |
+
return Braintree_Configuration::gateway()->creditCard()->fetchExpiring($startDate, $endDate, $ids);
|
236 |
+
}
|
237 |
+
|
238 |
+
public static function find($token)
|
239 |
+
{
|
240 |
+
return Braintree_Configuration::gateway()->creditCard()->find($token);
|
241 |
+
}
|
242 |
+
|
243 |
+
public static function fromNonce($nonce)
|
244 |
+
{
|
245 |
+
return Braintree_Configuration::gateway()->creditCard()->fromNonce($nonce);
|
246 |
+
}
|
247 |
+
|
248 |
+
public static function credit($token, $transactionAttribs)
|
249 |
+
{
|
250 |
+
return Braintree_Configuration::gateway()->creditCard()->credit($token, $transactionAttribs);
|
251 |
+
}
|
252 |
+
|
253 |
+
public static function creditNoValidate($token, $transactionAttribs)
|
254 |
+
{
|
255 |
+
return Braintree_Configuration::gateway()->creditCard()->creditNoValidate($token, $transactionAttribs);
|
256 |
+
}
|
257 |
+
|
258 |
+
public static function sale($token, $transactionAttribs)
|
259 |
+
{
|
260 |
+
return Braintree_Configuration::gateway()->creditCard()->sale($token, $transactionAttribs);
|
261 |
+
}
|
262 |
+
|
263 |
+
public static function saleNoValidate($token, $transactionAttribs)
|
264 |
+
{
|
265 |
+
return Braintree_Configuration::gateway()->creditCard()->saleNoValidate($token, $transactionAttribs);
|
266 |
+
}
|
267 |
+
|
268 |
+
public static function update($token, $attributes)
|
269 |
+
{
|
270 |
+
return Braintree_Configuration::gateway()->creditCard()->update($token, $attributes);
|
271 |
+
}
|
272 |
+
|
273 |
+
public static function updateNoValidate($token, $attributes)
|
274 |
+
{
|
275 |
+
return Braintree_Configuration::gateway()->creditCard()->updateNoValidate($token, $attributes);
|
276 |
+
}
|
277 |
+
|
278 |
+
public static function updateCreditCardUrl()
|
279 |
+
{
|
280 |
+
return Braintree_Configuration::gateway()->creditCard()->updateCreditCardUrl();
|
281 |
+
}
|
282 |
+
|
283 |
+
public static function updateFromTransparentRedirect($queryString)
|
284 |
+
{
|
285 |
+
return Braintree_Configuration::gateway()->creditCard()->updateFromTransparentRedirect($queryString);
|
286 |
+
}
|
287 |
+
|
288 |
+
public static function delete($token)
|
289 |
+
{
|
290 |
+
return Braintree_Configuration::gateway()->creditCard()->delete($token);
|
291 |
+
}
|
292 |
+
}
|
lib/Braintree/CreditCardGateway.php
ADDED
@@ -0,0 +1,471 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree CreditCardGateway module
|
4 |
+
* Creates and manages Braintree CreditCards
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* For more detailed information on CreditCards, see {@link http://www.braintreepayments.com/gateway/credit-card-api http://www.braintreepaymentsolutions.com/gateway/credit-card-api}<br />
|
9 |
+
* 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}
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @category Resources
|
13 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
14 |
+
*/
|
15 |
+
class Braintree_CreditCardGateway
|
16 |
+
{
|
17 |
+
private $_gateway;
|
18 |
+
private $_config;
|
19 |
+
private $_http;
|
20 |
+
|
21 |
+
public function __construct($gateway)
|
22 |
+
{
|
23 |
+
$this->_gateway = $gateway;
|
24 |
+
$this->_config = $gateway->config;
|
25 |
+
$this->_http = new Braintree_Http($gateway->config);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function create($attribs)
|
29 |
+
{
|
30 |
+
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
|
31 |
+
return $this->_doCreate('/payment_methods', array('credit_card' => $attribs));
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* attempts the create operation assuming all data will validate
|
36 |
+
* returns a Braintree_CreditCard object instead of a Result
|
37 |
+
*
|
38 |
+
* @access public
|
39 |
+
* @param array $attribs
|
40 |
+
* @return object
|
41 |
+
* @throws Braintree_Exception_ValidationError
|
42 |
+
*/
|
43 |
+
public function createNoValidate($attribs)
|
44 |
+
{
|
45 |
+
$result = $this->create($attribs);
|
46 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
47 |
+
}
|
48 |
+
/**
|
49 |
+
* create a customer from a TransparentRedirect operation
|
50 |
+
*
|
51 |
+
* @access public
|
52 |
+
* @param array $attribs
|
53 |
+
* @return object
|
54 |
+
*/
|
55 |
+
public function createFromTransparentRedirect($queryString)
|
56 |
+
{
|
57 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
|
58 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
59 |
+
$queryString
|
60 |
+
);
|
61 |
+
return $this->_doCreate(
|
62 |
+
'/payment_methods/all/confirm_transparent_redirect_request',
|
63 |
+
array('id' => $params['id'])
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
*
|
69 |
+
* @access public
|
70 |
+
* @param none
|
71 |
+
* @return string
|
72 |
+
*/
|
73 |
+
public function createCreditCardUrl()
|
74 |
+
{
|
75 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
|
76 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() .
|
77 |
+
'/payment_methods/all/create_via_transparent_redirect_request';
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* returns a ResourceCollection of expired credit cards
|
82 |
+
* @return object ResourceCollection
|
83 |
+
*/
|
84 |
+
public function expired()
|
85 |
+
{
|
86 |
+
$path = $this->_config->merchantPath() . '/payment_methods/all/expired_ids';
|
87 |
+
$response = $this->_http->post($path);
|
88 |
+
$pager = array(
|
89 |
+
'object' => $this,
|
90 |
+
'method' => 'fetchExpired',
|
91 |
+
'methodArgs' => array()
|
92 |
+
);
|
93 |
+
|
94 |
+
return new Braintree_ResourceCollection($response, $pager);
|
95 |
+
}
|
96 |
+
|
97 |
+
public function fetchExpired($ids)
|
98 |
+
{
|
99 |
+
$path = $this->_config->merchantPath() . "/payment_methods/all/expired";
|
100 |
+
$response = $this->_http->post($path, array('search' => array('ids' => $ids)));
|
101 |
+
|
102 |
+
return Braintree_Util::extractattributeasarray(
|
103 |
+
$response['paymentMethods'],
|
104 |
+
'creditCard'
|
105 |
+
);
|
106 |
+
}
|
107 |
+
/**
|
108 |
+
* returns a ResourceCollection of credit cards expiring between start/end
|
109 |
+
*
|
110 |
+
* @return object ResourceCollection
|
111 |
+
*/
|
112 |
+
public function expiringBetween($startDate, $endDate)
|
113 |
+
{
|
114 |
+
$queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
|
115 |
+
$response = $this->_http->post($queryPath);
|
116 |
+
$pager = array(
|
117 |
+
'object' => $this,
|
118 |
+
'method' => 'fetchExpiring',
|
119 |
+
'methodArgs' => array($startDate, $endDate)
|
120 |
+
);
|
121 |
+
|
122 |
+
return new Braintree_ResourceCollection($response, $pager);
|
123 |
+
}
|
124 |
+
|
125 |
+
public function fetchExpiring($startDate, $endDate, $ids)
|
126 |
+
{
|
127 |
+
$queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
|
128 |
+
$response = $this->_http->post($queryPath, array('search' => array('ids' => $ids)));
|
129 |
+
|
130 |
+
return Braintree_Util::extractAttributeAsArray(
|
131 |
+
$response['paymentMethods'],
|
132 |
+
'creditCard'
|
133 |
+
);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* find a creditcard by token
|
138 |
+
*
|
139 |
+
* @access public
|
140 |
+
* @param string $token credit card unique id
|
141 |
+
* @return object Braintree_CreditCard
|
142 |
+
* @throws Braintree_Exception_NotFound
|
143 |
+
*/
|
144 |
+
public function find($token)
|
145 |
+
{
|
146 |
+
$this->_validateId($token);
|
147 |
+
try {
|
148 |
+
$path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
|
149 |
+
$response = $this->_http->get($path);
|
150 |
+
return Braintree_CreditCard::factory($response['creditCard']);
|
151 |
+
} catch (Braintree_Exception_NotFound $e) {
|
152 |
+
throw new Braintree_Exception_NotFound(
|
153 |
+
'credit card with token ' . $token . ' not found'
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Convert a payment method nonce to a credit card
|
161 |
+
*
|
162 |
+
* @access public
|
163 |
+
* @param string $nonce payment method nonce
|
164 |
+
* @return object Braintree_CreditCard
|
165 |
+
* @throws Braintree_Exception_NotFound
|
166 |
+
*/
|
167 |
+
public function fromNonce($nonce)
|
168 |
+
{
|
169 |
+
$this->_validateId($nonce, "nonce");
|
170 |
+
try {
|
171 |
+
$path = $this->_config->merchantPath() . '/payment_methods/from_nonce/' . $nonce;
|
172 |
+
$response = $this->_http->get($path);
|
173 |
+
return Braintree_CreditCard::factory($response['creditCard']);
|
174 |
+
} catch (Braintree_Exception_NotFound $e) {
|
175 |
+
throw new Braintree_Exception_NotFound(
|
176 |
+
'credit card with nonce ' . $nonce . ' locked, consumed or not found'
|
177 |
+
);
|
178 |
+
}
|
179 |
+
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* create a credit on the card for the passed transaction
|
184 |
+
*
|
185 |
+
* @access public
|
186 |
+
* @param array $attribs
|
187 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
188 |
+
*/
|
189 |
+
public function credit($token, $transactionAttribs)
|
190 |
+
{
|
191 |
+
$this->_validateId($token);
|
192 |
+
return Braintree_Transaction::credit(
|
193 |
+
array_merge(
|
194 |
+
$transactionAttribs,
|
195 |
+
array('paymentMethodToken' => $token)
|
196 |
+
)
|
197 |
+
);
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* create a credit on this card, assuming validations will pass
|
202 |
+
*
|
203 |
+
* returns a Braintree_Transaction object on success
|
204 |
+
*
|
205 |
+
* @access public
|
206 |
+
* @param array $attribs
|
207 |
+
* @return object Braintree_Transaction
|
208 |
+
* @throws Braintree_Exception_ValidationError
|
209 |
+
*/
|
210 |
+
public function creditNoValidate($token, $transactionAttribs)
|
211 |
+
{
|
212 |
+
$result = $this->credit($token, $transactionAttribs);
|
213 |
+
return Braintree_Util::returnObjectOrThrowException('Transaction', $result);
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* create a new sale for the current card
|
218 |
+
*
|
219 |
+
* @param string $token
|
220 |
+
* @param array $transactionAttribs
|
221 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
222 |
+
* @see Braintree_Transaction::sale()
|
223 |
+
*/
|
224 |
+
public function sale($token, $transactionAttribs)
|
225 |
+
{
|
226 |
+
$this->_validateId($token);
|
227 |
+
return Braintree_Transaction::sale(
|
228 |
+
array_merge(
|
229 |
+
$transactionAttribs,
|
230 |
+
array('paymentMethodToken' => $token)
|
231 |
+
)
|
232 |
+
);
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* create a new sale using this card, assuming validations will pass
|
237 |
+
*
|
238 |
+
* returns a Braintree_Transaction object on success
|
239 |
+
*
|
240 |
+
* @access public
|
241 |
+
* @param array $transactionAttribs
|
242 |
+
* @param string $token
|
243 |
+
* @return object Braintree_Transaction
|
244 |
+
* @throws Braintree_Exception_ValidationsFailed
|
245 |
+
* @see Braintree_Transaction::sale()
|
246 |
+
*/
|
247 |
+
public function saleNoValidate($token, $transactionAttribs)
|
248 |
+
{
|
249 |
+
$result = $this->sale($token, $transactionAttribs);
|
250 |
+
return Braintree_Util::returnObjectOrThrowException('Transaction', $result);
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* updates the creditcard record
|
255 |
+
*
|
256 |
+
* if calling this method in context, $token
|
257 |
+
* is the 2nd attribute. $token is not sent in object context.
|
258 |
+
*
|
259 |
+
* @access public
|
260 |
+
* @param array $attributes
|
261 |
+
* @param string $token (optional)
|
262 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
263 |
+
*/
|
264 |
+
public function update($token, $attributes)
|
265 |
+
{
|
266 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
|
267 |
+
$this->_validateId($token);
|
268 |
+
return $this->_doUpdate('put', '/payment_methods/credit_card/' . $token, array('creditCard' => $attributes));
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* update a creditcard record, assuming validations will pass
|
273 |
+
*
|
274 |
+
* if calling this method in context, $token
|
275 |
+
* is the 2nd attribute. $token is not sent in object context.
|
276 |
+
* returns a Braintree_CreditCard object on success
|
277 |
+
*
|
278 |
+
* @access public
|
279 |
+
* @param array $attributes
|
280 |
+
* @param string $token
|
281 |
+
* @return object Braintree_CreditCard
|
282 |
+
* @throws Braintree_Exception_ValidationsFailed
|
283 |
+
*/
|
284 |
+
public function updateNoValidate($token, $attributes)
|
285 |
+
{
|
286 |
+
$result = $this->update($token, $attributes);
|
287 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
288 |
+
}
|
289 |
+
/**
|
290 |
+
*
|
291 |
+
* @access public
|
292 |
+
* @param none
|
293 |
+
* @return string
|
294 |
+
*/
|
295 |
+
public function updateCreditCardUrl()
|
296 |
+
{
|
297 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
|
298 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() .
|
299 |
+
'/payment_methods/all/update_via_transparent_redirect_request';
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* update a customer from a TransparentRedirect operation
|
304 |
+
*
|
305 |
+
* @access public
|
306 |
+
* @param array $attribs
|
307 |
+
* @return object
|
308 |
+
*/
|
309 |
+
public function updateFromTransparentRedirect($queryString)
|
310 |
+
{
|
311 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
|
312 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
313 |
+
$queryString
|
314 |
+
);
|
315 |
+
return $this->_doUpdate(
|
316 |
+
'post',
|
317 |
+
'/payment_methods/all/confirm_transparent_redirect_request',
|
318 |
+
array('id' => $params['id'])
|
319 |
+
);
|
320 |
+
}
|
321 |
+
|
322 |
+
public function delete($token)
|
323 |
+
{
|
324 |
+
$this->_validateId($token);
|
325 |
+
$path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
|
326 |
+
$this->_http->delete($path);
|
327 |
+
return new Braintree_Result_Successful();
|
328 |
+
}
|
329 |
+
|
330 |
+
private static function baseOptions()
|
331 |
+
{
|
332 |
+
return array('makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession');
|
333 |
+
}
|
334 |
+
|
335 |
+
private static function baseSignature($options)
|
336 |
+
{
|
337 |
+
return array(
|
338 |
+
'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId',
|
339 |
+
'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode',
|
340 |
+
'deviceData', 'fraudMerchantId', 'paymentMethodNonce',
|
341 |
+
array('options' => $options),
|
342 |
+
array(
|
343 |
+
'billingAddress' => array(
|
344 |
+
'firstName',
|
345 |
+
'lastName',
|
346 |
+
'company',
|
347 |
+
'countryCodeAlpha2',
|
348 |
+
'countryCodeAlpha3',
|
349 |
+
'countryCodeNumeric',
|
350 |
+
'countryName',
|
351 |
+
'extendedAddress',
|
352 |
+
'locality',
|
353 |
+
'region',
|
354 |
+
'postalCode',
|
355 |
+
'streetAddress'
|
356 |
+
),
|
357 |
+
),
|
358 |
+
);
|
359 |
+
}
|
360 |
+
|
361 |
+
public static function createSignature()
|
362 |
+
{
|
363 |
+
$options = self::baseOptions();
|
364 |
+
$options[] = "failOnDuplicatePaymentMethod";
|
365 |
+
$signature = self::baseSignature($options);
|
366 |
+
$signature[] = 'customerId';
|
367 |
+
return $signature;
|
368 |
+
}
|
369 |
+
|
370 |
+
public static function updateSignature()
|
371 |
+
{
|
372 |
+
$signature = self::baseSignature(self::baseOptions());
|
373 |
+
|
374 |
+
$updateExistingBillingSignature = array(
|
375 |
+
array(
|
376 |
+
'options' => array(
|
377 |
+
'updateExisting'
|
378 |
+
)
|
379 |
+
)
|
380 |
+
);
|
381 |
+
|
382 |
+
foreach($signature AS $key => $value) {
|
383 |
+
if(is_array($value) and array_key_exists('billingAddress', $value)) {
|
384 |
+
$signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature);
|
385 |
+
}
|
386 |
+
}
|
387 |
+
|
388 |
+
return $signature;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* sends the create request to the gateway
|
393 |
+
*
|
394 |
+
* @ignore
|
395 |
+
* @param string $subPath
|
396 |
+
* @param array $params
|
397 |
+
* @return mixed
|
398 |
+
*/
|
399 |
+
public function _doCreate($subPath, $params)
|
400 |
+
{
|
401 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
402 |
+
$response = $this->_http->post($fullPath, $params);
|
403 |
+
|
404 |
+
return $this->_verifyGatewayResponse($response);
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* verifies that a valid credit card identifier is being used
|
409 |
+
* @ignore
|
410 |
+
* @param string $identifier
|
411 |
+
* @param Optional $string $identifierType type of identifier supplied, default "token"
|
412 |
+
* @throws InvalidArgumentException
|
413 |
+
*/
|
414 |
+
private function _validateId($identifier = null, $identifierType = "token")
|
415 |
+
{
|
416 |
+
if (empty($identifier)) {
|
417 |
+
throw new InvalidArgumentException(
|
418 |
+
'expected credit card id to be set'
|
419 |
+
);
|
420 |
+
}
|
421 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
|
422 |
+
throw new InvalidArgumentException(
|
423 |
+
$identifier . ' is an invalid credit card ' . $identifierType . '.'
|
424 |
+
);
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* sends the update request to the gateway
|
430 |
+
*
|
431 |
+
* @ignore
|
432 |
+
* @param string $url
|
433 |
+
* @param array $params
|
434 |
+
* @return mixed
|
435 |
+
*/
|
436 |
+
private function _doUpdate($httpVerb, $subPath, $params)
|
437 |
+
{
|
438 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
439 |
+
$response = $this->_http->$httpVerb($fullPath, $params);
|
440 |
+
return $this->_verifyGatewayResponse($response);
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* generic method for validating incoming gateway responses
|
445 |
+
*
|
446 |
+
* creates a new Braintree_CreditCard object and encapsulates
|
447 |
+
* it inside a Braintree_Result_Successful object, or
|
448 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
449 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
450 |
+
*
|
451 |
+
* @ignore
|
452 |
+
* @param array $response gateway response values
|
453 |
+
* @return object Result_Successful or Result_Error
|
454 |
+
* @throws Braintree_Exception_Unexpected
|
455 |
+
*/
|
456 |
+
private function _verifyGatewayResponse($response)
|
457 |
+
{
|
458 |
+
if (isset($response['creditCard'])) {
|
459 |
+
// return a populated instance of Braintree_Address
|
460 |
+
return new Braintree_Result_Successful(
|
461 |
+
Braintree_CreditCard::factory($response['creditCard'])
|
462 |
+
);
|
463 |
+
} else if (isset($response['apiErrorResponse'])) {
|
464 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
465 |
+
} else {
|
466 |
+
throw new Braintree_Exception_Unexpected(
|
467 |
+
"Expected address or apiErrorResponse"
|
468 |
+
);
|
469 |
+
}
|
470 |
+
}
|
471 |
+
}
|
lib/Braintree/CreditCardVerification.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_CreditCardVerification extends Braintree_Result_CreditCardVerification
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self($attributes);
|
7 |
+
return $instance;
|
8 |
+
}
|
9 |
+
|
10 |
+
|
11 |
+
// static methods redirecting to gateway
|
12 |
+
|
13 |
+
public static function fetch($query, $ids)
|
14 |
+
{
|
15 |
+
return Braintree_Configuration::gateway()->creditCardVerification()->fetch($query, $ids);
|
16 |
+
}
|
17 |
+
|
18 |
+
public static function search($query)
|
19 |
+
{
|
20 |
+
return Braintree_Configuration::gateway()->creditCardVerification()->search($query);
|
21 |
+
}
|
22 |
+
}
|
lib/Braintree/CreditCardVerificationGateway.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_CreditCardVerificationGateway
|
3 |
+
{
|
4 |
+
private $_gateway;
|
5 |
+
private $_config;
|
6 |
+
private $_http;
|
7 |
+
|
8 |
+
public function __construct($gateway)
|
9 |
+
{
|
10 |
+
$this->_gateway = $gateway;
|
11 |
+
$this->_config = $gateway->config;
|
12 |
+
$this->_http = new Braintree_Http($gateway->config);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function fetch($query, $ids)
|
16 |
+
{
|
17 |
+
$criteria = array();
|
18 |
+
foreach ($query as $term) {
|
19 |
+
$criteria[$term->name] = $term->toparam();
|
20 |
+
}
|
21 |
+
$criteria["ids"] = Braintree_CreditCardVerificationSearch::ids()->in($ids)->toparam();
|
22 |
+
$path = $this->_config->merchantPath() . '/verifications/advanced_search';
|
23 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
24 |
+
|
25 |
+
return Braintree_Util::extractattributeasarray(
|
26 |
+
$response['creditCardVerifications'],
|
27 |
+
'verification'
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function search($query)
|
32 |
+
{
|
33 |
+
$criteria = array();
|
34 |
+
foreach ($query as $term) {
|
35 |
+
$criteria[$term->name] = $term->toparam();
|
36 |
+
}
|
37 |
+
|
38 |
+
$path = $this->_config->merchantPath() . '/verifications/advanced_search_ids';
|
39 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
40 |
+
$pager = array(
|
41 |
+
'object' => $this,
|
42 |
+
'method' => 'fetch',
|
43 |
+
'methodArgs' => array($query)
|
44 |
+
);
|
45 |
+
|
46 |
+
return new Braintree_ResourceCollection($response, $pager);
|
47 |
+
}
|
48 |
+
}
|
lib/Braintree/CreditCardVerificationSearch.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_CreditCardVerificationSearch
|
3 |
+
{
|
4 |
+
static function id() { return new Braintree_TextNode('id'); }
|
5 |
+
static function creditCardCardholderName() { return new Braintree_TextNode('credit_card_cardholder_name'); }
|
6 |
+
|
7 |
+
static function creditCardExpirationDate() { return new Braintree_EqualityNode('credit_card_expiration_date'); }
|
8 |
+
static function creditCardNumber() { return new Braintree_PartialMatchNode('credit_card_number'); }
|
9 |
+
|
10 |
+
static function ids() { return new Braintree_MultipleValueNode('ids'); }
|
11 |
+
|
12 |
+
static function creditCardCardType()
|
13 |
+
{
|
14 |
+
return new Braintree_MultipleValueNode("credit_card_card_type", array(
|
15 |
+
Braintree_CreditCard::AMEX,
|
16 |
+
Braintree_CreditCard::CARTE_BLANCHE,
|
17 |
+
Braintree_CreditCard::CHINA_UNION_PAY,
|
18 |
+
Braintree_CreditCard::DINERS_CLUB_INTERNATIONAL,
|
19 |
+
Braintree_CreditCard::DISCOVER,
|
20 |
+
Braintree_CreditCard::JCB,
|
21 |
+
Braintree_CreditCard::LASER,
|
22 |
+
Braintree_CreditCard::MAESTRO,
|
23 |
+
Braintree_CreditCard::MASTER_CARD,
|
24 |
+
Braintree_CreditCard::SOLO,
|
25 |
+
Braintree_CreditCard::SWITCH_TYPE,
|
26 |
+
Braintree_CreditCard::VISA,
|
27 |
+
Braintree_CreditCard::UNKNOWN
|
28 |
+
));
|
29 |
+
}
|
30 |
+
|
31 |
+
|
32 |
+
static function createdAt() { return new Braintree_RangeNode("created_at"); }
|
33 |
+
}
|
lib/Braintree/Customer.php
ADDED
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Customer module
|
4 |
+
* Creates and manages Customers
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* For more detailed information on Customers, see {@link http://www.braintreepayments.com/gateway/customer-api http://www.braintreepaymentsolutions.com/gateway/customer-api}
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @category Resources
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*
|
14 |
+
* @property-read array $addresses
|
15 |
+
* @property-read array $applePayCards
|
16 |
+
* @property-read string $company
|
17 |
+
* @property-read string $createdAt
|
18 |
+
* @property-read array $creditCards
|
19 |
+
* @property-read array $coinbaseAccounts
|
20 |
+
* @property-read array $paypalAccounts
|
21 |
+
* @property-read array $customFields custom fields passed with the request
|
22 |
+
* @property-read string $email
|
23 |
+
* @property-read string $fax
|
24 |
+
* @property-read string $firstName
|
25 |
+
* @property-read string $id
|
26 |
+
* @property-read string $lastName
|
27 |
+
* @property-read string $phone
|
28 |
+
* @property-read string $updatedAt
|
29 |
+
* @property-read string $website
|
30 |
+
*/
|
31 |
+
class Braintree_Customer extends Braintree
|
32 |
+
{
|
33 |
+
public static function all()
|
34 |
+
{
|
35 |
+
return Braintree_Configuration::gateway()->customer()->all();
|
36 |
+
}
|
37 |
+
|
38 |
+
public static function fetch($query, $ids)
|
39 |
+
{
|
40 |
+
return Braintree_Configuration::gateway()->customer()->fetch($query, $ids);
|
41 |
+
}
|
42 |
+
|
43 |
+
public static function create($attribs = array())
|
44 |
+
{
|
45 |
+
return Braintree_Configuration::gateway()->customer()->create($attribs);
|
46 |
+
}
|
47 |
+
|
48 |
+
public static function createNoValidate($attribs = array())
|
49 |
+
{
|
50 |
+
return Braintree_Configuration::gateway()->customer()->createNoValidate($attribs);
|
51 |
+
}
|
52 |
+
|
53 |
+
public static function createFromTransparentRedirect($queryString)
|
54 |
+
{
|
55 |
+
return Braintree_Configuration::gateway()->customer()->createFromTransparentRedirect($queryString);
|
56 |
+
}
|
57 |
+
|
58 |
+
public static function createCustomerUrl()
|
59 |
+
{
|
60 |
+
return Braintree_Configuration::gateway()->customer()->createCustomerUrl();
|
61 |
+
}
|
62 |
+
|
63 |
+
public static function find($id)
|
64 |
+
{
|
65 |
+
return Braintree_Configuration::gateway()->customer()->find($id);
|
66 |
+
}
|
67 |
+
|
68 |
+
public static function credit($customerId, $transactionAttribs)
|
69 |
+
{
|
70 |
+
return Braintree_Configuration::gateway()->customer()->credit($customerId, $transactionAttribs);
|
71 |
+
}
|
72 |
+
|
73 |
+
public static function creditNoValidate($customerId, $transactionAttribs)
|
74 |
+
{
|
75 |
+
return Braintree_Configuration::gateway()->customer()->creditNoValidate($customerId, $transactionAttribs);
|
76 |
+
}
|
77 |
+
|
78 |
+
public static function delete($customerId)
|
79 |
+
{
|
80 |
+
return Braintree_Configuration::gateway()->customer()->delete($customerId);
|
81 |
+
}
|
82 |
+
|
83 |
+
public static function sale($customerId, $transactionAttribs)
|
84 |
+
{
|
85 |
+
return Braintree_Configuration::gateway()->customer()->sale($customerId, $transactionAttribs);
|
86 |
+
}
|
87 |
+
|
88 |
+
public static function saleNoValidate($customerId, $transactionAttribs)
|
89 |
+
{
|
90 |
+
return Braintree_Configuration::gateway()->customer()->saleNoValidate($customerId, $transactionAttribs);
|
91 |
+
}
|
92 |
+
|
93 |
+
public static function search($query)
|
94 |
+
{
|
95 |
+
return Braintree_Configuration::gateway()->customer()->search($query);
|
96 |
+
}
|
97 |
+
|
98 |
+
public static function update($customerId, $attributes)
|
99 |
+
{
|
100 |
+
return Braintree_Configuration::gateway()->customer()->update($customerId, $attributes);
|
101 |
+
}
|
102 |
+
|
103 |
+
public static function updateNoValidate($customerId, $attributes)
|
104 |
+
{
|
105 |
+
return Braintree_Configuration::gateway()->customer()->updateNoValidate($customerId, $attributes);
|
106 |
+
}
|
107 |
+
|
108 |
+
public static function updateCustomerUrl()
|
109 |
+
{
|
110 |
+
return Braintree_Configuration::gateway()->customer()->updateCustomerUrl();
|
111 |
+
}
|
112 |
+
|
113 |
+
public static function updateFromTransparentRedirect($queryString)
|
114 |
+
{
|
115 |
+
return Braintree_Configuration::gateway()->customer()->updateFromTransparentRedirect($queryString);
|
116 |
+
}
|
117 |
+
|
118 |
+
/* instance methods */
|
119 |
+
|
120 |
+
/**
|
121 |
+
* sets instance properties from an array of values
|
122 |
+
*
|
123 |
+
* @ignore
|
124 |
+
* @access protected
|
125 |
+
* @param array $customerAttribs array of customer data
|
126 |
+
* @return none
|
127 |
+
*/
|
128 |
+
protected function _initialize($customerAttribs)
|
129 |
+
{
|
130 |
+
// set the attributes
|
131 |
+
$this->_attributes = $customerAttribs;
|
132 |
+
|
133 |
+
// map each address into its own object
|
134 |
+
$addressArray = array();
|
135 |
+
if (isset($customerAttribs['addresses'])) {
|
136 |
+
|
137 |
+
foreach ($customerAttribs['addresses'] AS $address) {
|
138 |
+
$addressArray[] = Braintree_Address::factory($address);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
$this->_set('addresses', $addressArray);
|
142 |
+
|
143 |
+
// map each creditCard into its own object
|
144 |
+
$creditCardArray = array();
|
145 |
+
if (isset($customerAttribs['creditCards'])) {
|
146 |
+
foreach ($customerAttribs['creditCards'] AS $creditCard) {
|
147 |
+
$creditCardArray[] = Braintree_CreditCard::factory($creditCard);
|
148 |
+
}
|
149 |
+
}
|
150 |
+
$this->_set('creditCards', $creditCardArray);
|
151 |
+
|
152 |
+
// map each coinbaseAccount into its own object
|
153 |
+
$coinbaseAccountArray = array();
|
154 |
+
if (isset($customerAttribs['coinbaseAccounts'])) {
|
155 |
+
foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) {
|
156 |
+
$coinbaseAccountArray[] = Braintree_CoinbaseAccount::factory($coinbaseAccount);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
$this->_set('coinbaseAccounts', $coinbaseAccountArray);
|
160 |
+
|
161 |
+
// map each paypalAccount into its own object
|
162 |
+
$paypalAccountArray = array();
|
163 |
+
if (isset($customerAttribs['paypalAccounts'])) {
|
164 |
+
foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) {
|
165 |
+
$paypalAccountArray[] = Braintree_PayPalAccount::factory($paypalAccount);
|
166 |
+
}
|
167 |
+
}
|
168 |
+
$this->_set('paypalAccounts', $paypalAccountArray);
|
169 |
+
|
170 |
+
// map each applePayCard into its own object
|
171 |
+
$applePayCardArray = array();
|
172 |
+
if (isset($customerAttribs['applePayCards'])) {
|
173 |
+
foreach ($customerAttribs['applePayCards'] AS $applePayCard) {
|
174 |
+
$applePayCardArray[] = Braintree_applePayCard::factory($applePayCard);
|
175 |
+
}
|
176 |
+
}
|
177 |
+
$this->_set('applePayCards', $applePayCardArray);
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* returns a string representation of the customer
|
182 |
+
* @return string
|
183 |
+
*/
|
184 |
+
public function __toString()
|
185 |
+
{
|
186 |
+
return __CLASS__ . '[' .
|
187 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* returns false if comparing object is not a Braintree_Customer,
|
192 |
+
* or is a Braintree_Customer with a different id
|
193 |
+
*
|
194 |
+
* @param object $otherCust customer to compare against
|
195 |
+
* @return boolean
|
196 |
+
*/
|
197 |
+
public function isEqual($otherCust)
|
198 |
+
{
|
199 |
+
return !($otherCust instanceof Braintree_Customer) ? false : $this->id === $otherCust->id;
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* returns an array containt all of the customer's payment methods
|
204 |
+
*
|
205 |
+
* @return array
|
206 |
+
*/
|
207 |
+
public function paymentMethods()
|
208 |
+
{
|
209 |
+
return array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts);
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* returns the customer's default payment method
|
214 |
+
*
|
215 |
+
* @return object Braintree_CreditCard or Braintree_PayPalAccount
|
216 |
+
*/
|
217 |
+
public function defaultPaymentMethod()
|
218 |
+
{
|
219 |
+
$defaultPaymentMethods = array_filter($this->paymentMethods(), 'Braintree_Customer::_defaultPaymentMethodFilter');
|
220 |
+
return current($defaultPaymentMethods);
|
221 |
+
}
|
222 |
+
|
223 |
+
public static function _defaultPaymentMethodFilter($paymentMethod)
|
224 |
+
{
|
225 |
+
return $paymentMethod->isDefault();
|
226 |
+
}
|
227 |
+
|
228 |
+
/* private class properties */
|
229 |
+
|
230 |
+
/**
|
231 |
+
* @access protected
|
232 |
+
* @var array registry of customer data
|
233 |
+
*/
|
234 |
+
protected $_attributes = array(
|
235 |
+
'addresses' => '',
|
236 |
+
'company' => '',
|
237 |
+
'creditCards' => '',
|
238 |
+
'email' => '',
|
239 |
+
'fax' => '',
|
240 |
+
'firstName' => '',
|
241 |
+
'id' => '',
|
242 |
+
'lastName' => '',
|
243 |
+
'phone' => '',
|
244 |
+
'createdAt' => '',
|
245 |
+
'updatedAt' => '',
|
246 |
+
'website' => '',
|
247 |
+
);
|
248 |
+
|
249 |
+
/**
|
250 |
+
* factory method: returns an instance of Braintree_Customer
|
251 |
+
* to the requesting method, with populated properties
|
252 |
+
*
|
253 |
+
* @ignore
|
254 |
+
* @return object instance of Braintree_Customer
|
255 |
+
*/
|
256 |
+
public static function factory($attributes)
|
257 |
+
{
|
258 |
+
$instance = new Braintree_Customer();
|
259 |
+
$instance->_initialize($attributes);
|
260 |
+
return $instance;
|
261 |
+
}
|
262 |
+
}
|
lib/Braintree/CustomerGateway.php
ADDED
@@ -0,0 +1,594 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree CustomerGateway module
|
4 |
+
* Creates and manages Customers
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* For more detailed information on Customers, see {@link http://www.braintreepayments.com/gateway/customer-api http://www.braintreepaymentsolutions.com/gateway/customer-api}
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @category Resources
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_CustomerGateway
|
15 |
+
{
|
16 |
+
private $_gateway;
|
17 |
+
private $_config;
|
18 |
+
private $_http;
|
19 |
+
|
20 |
+
public function __construct($gateway)
|
21 |
+
{
|
22 |
+
$this->_gateway = $gateway;
|
23 |
+
$this->_config = $gateway->config;
|
24 |
+
$this->_http = new Braintree_Http($gateway->config);
|
25 |
+
}
|
26 |
+
|
27 |
+
public function all()
|
28 |
+
{
|
29 |
+
$path = $this->_config->merchantPath() . '/customers/advanced_search_ids';
|
30 |
+
$response = $this->_http->post($path);
|
31 |
+
$pager = array(
|
32 |
+
'object' => $this,
|
33 |
+
'method' => 'fetch',
|
34 |
+
'methodArgs' => array(array())
|
35 |
+
);
|
36 |
+
|
37 |
+
return new Braintree_ResourceCollection($response, $pager);
|
38 |
+
}
|
39 |
+
|
40 |
+
public function fetch($query, $ids)
|
41 |
+
{
|
42 |
+
$criteria = array();
|
43 |
+
foreach ($query as $term) {
|
44 |
+
$criteria[$term->name] = $term->toparam();
|
45 |
+
}
|
46 |
+
$criteria["ids"] = Braintree_CustomerSearch::ids()->in($ids)->toparam();
|
47 |
+
$path = $this->_config->merchantPath() . '/customers/advanced_search';
|
48 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
49 |
+
|
50 |
+
return Braintree_Util::extractattributeasarray(
|
51 |
+
$response['customers'],
|
52 |
+
'customer'
|
53 |
+
);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Creates a customer using the given +attributes+. If <tt>:id</tt> is not passed,
|
58 |
+
* the gateway will generate it.
|
59 |
+
*
|
60 |
+
* <code>
|
61 |
+
* $result = Braintree_Customer::create(array(
|
62 |
+
* 'first_name' => 'John',
|
63 |
+
* 'last_name' => 'Smith',
|
64 |
+
* 'company' => 'Smith Co.',
|
65 |
+
* 'email' => 'john@smith.com',
|
66 |
+
* 'website' => 'www.smithco.com',
|
67 |
+
* 'fax' => '419-555-1234',
|
68 |
+
* 'phone' => '614-555-1234'
|
69 |
+
* ));
|
70 |
+
* if($result->success) {
|
71 |
+
* echo 'Created customer ' . $result->customer->id;
|
72 |
+
* } else {
|
73 |
+
* echo 'Could not create customer, see result->errors';
|
74 |
+
* }
|
75 |
+
* </code>
|
76 |
+
*
|
77 |
+
* @access public
|
78 |
+
* @param array $attribs
|
79 |
+
* @return object Result, either Successful or Error
|
80 |
+
*/
|
81 |
+
public function create($attribs = array())
|
82 |
+
{
|
83 |
+
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
|
84 |
+
return $this->_doCreate('/customers', array('customer' => $attribs));
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* attempts the create operation assuming all data will validate
|
89 |
+
* returns a Braintree_Customer object instead of a Result
|
90 |
+
*
|
91 |
+
* @access public
|
92 |
+
* @param array $attribs
|
93 |
+
* @return object
|
94 |
+
* @throws Braintree_Exception_ValidationError
|
95 |
+
*/
|
96 |
+
public function createNoValidate($attribs = array())
|
97 |
+
{
|
98 |
+
$result = $this->create($attribs);
|
99 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
100 |
+
}
|
101 |
+
/**
|
102 |
+
* create a customer from a TransparentRedirect operation
|
103 |
+
*
|
104 |
+
* @access public
|
105 |
+
* @param array $attribs
|
106 |
+
* @return object
|
107 |
+
*/
|
108 |
+
public function createFromTransparentRedirect($queryString)
|
109 |
+
{
|
110 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
|
111 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
112 |
+
$queryString
|
113 |
+
);
|
114 |
+
return $this->_doCreate(
|
115 |
+
'/customers/all/confirm_transparent_redirect_request',
|
116 |
+
array('id' => $params['id'])
|
117 |
+
);
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
*
|
122 |
+
* @access public
|
123 |
+
* @param none
|
124 |
+
* @return string
|
125 |
+
*/
|
126 |
+
public function createCustomerUrl()
|
127 |
+
{
|
128 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
|
129 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() .
|
130 |
+
'/customers/all/create_via_transparent_redirect_request';
|
131 |
+
}
|
132 |
+
|
133 |
+
|
134 |
+
/**
|
135 |
+
* creates a full array signature of a valid create request
|
136 |
+
* @return array gateway create request format
|
137 |
+
*/
|
138 |
+
public static function createSignature()
|
139 |
+
{
|
140 |
+
|
141 |
+
$creditCardSignature = Braintree_CreditCardGateway::createSignature();
|
142 |
+
unset($creditCardSignature['customerId']);
|
143 |
+
$signature = array(
|
144 |
+
'id', 'company', 'email', 'fax', 'firstName',
|
145 |
+
'lastName', 'phone', 'website', 'deviceData',
|
146 |
+
'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce',
|
147 |
+
array('creditCard' => $creditCardSignature),
|
148 |
+
array('customFields' => array('_anyKey_')),
|
149 |
+
);
|
150 |
+
return $signature;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* creates a full array signature of a valid update request
|
155 |
+
* @return array update request format
|
156 |
+
*/
|
157 |
+
public static function updateSignature()
|
158 |
+
{
|
159 |
+
$creditCardSignature = Braintree_CreditCardGateway::updateSignature();
|
160 |
+
|
161 |
+
foreach($creditCardSignature AS $key => $value) {
|
162 |
+
if(is_array($value) and array_key_exists('options', $value)) {
|
163 |
+
array_push($creditCardSignature[$key]['options'], 'updateExistingToken');
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
$signature = array(
|
168 |
+
'id', 'company', 'email', 'fax', 'firstName',
|
169 |
+
'lastName', 'phone', 'website', 'deviceData',
|
170 |
+
'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce',
|
171 |
+
array('creditCard' => $creditCardSignature),
|
172 |
+
array('customFields' => array('_anyKey_')),
|
173 |
+
);
|
174 |
+
return $signature;
|
175 |
+
}
|
176 |
+
|
177 |
+
|
178 |
+
/**
|
179 |
+
* find a customer by id
|
180 |
+
*
|
181 |
+
* @access public
|
182 |
+
* @param string id customer Id
|
183 |
+
* @return object Braintree_Customer
|
184 |
+
* @throws Braintree_Exception_NotFound
|
185 |
+
*/
|
186 |
+
public function find($id)
|
187 |
+
{
|
188 |
+
$this->_validateId($id);
|
189 |
+
try {
|
190 |
+
$path = $this->_config->merchantPath() . '/customers/' . $id;
|
191 |
+
$response = $this->_http->get($path);
|
192 |
+
return Braintree_Customer::factory($response['customer']);
|
193 |
+
} catch (Braintree_Exception_NotFound $e) {
|
194 |
+
throw new Braintree_Exception_NotFound(
|
195 |
+
'customer with id ' . $id . ' not found'
|
196 |
+
);
|
197 |
+
}
|
198 |
+
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* credit a customer for the passed transaction
|
203 |
+
*
|
204 |
+
* @access public
|
205 |
+
* @param array $attribs
|
206 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
207 |
+
*/
|
208 |
+
public function credit($customerId, $transactionAttribs)
|
209 |
+
{
|
210 |
+
$this->_validateId($customerId);
|
211 |
+
return Braintree_Transaction::credit(
|
212 |
+
array_merge($transactionAttribs,
|
213 |
+
array('customerId' => $customerId)
|
214 |
+
)
|
215 |
+
);
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* credit a customer, assuming validations will pass
|
220 |
+
*
|
221 |
+
* returns a Braintree_Transaction object on success
|
222 |
+
*
|
223 |
+
* @access public
|
224 |
+
* @param array $attribs
|
225 |
+
* @return object Braintree_Transaction
|
226 |
+
* @throws Braintree_Exception_ValidationError
|
227 |
+
*/
|
228 |
+
public function creditNoValidate($customerId, $transactionAttribs)
|
229 |
+
{
|
230 |
+
$result = $this->credit($customerId, $transactionAttribs);
|
231 |
+
return Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $result);
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* delete a customer by id
|
236 |
+
*
|
237 |
+
* @param string $customerId
|
238 |
+
*/
|
239 |
+
public function delete($customerId)
|
240 |
+
{
|
241 |
+
$this->_validateId($customerId);
|
242 |
+
$path = $this->_config->merchantPath() . '/customers/' . $customerId;
|
243 |
+
$this->_http->delete($path);
|
244 |
+
return new Braintree_Result_Successful();
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* create a new sale for a customer
|
249 |
+
*
|
250 |
+
* @param string $customerId
|
251 |
+
* @param array $transactionAttribs
|
252 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
253 |
+
* @see Braintree_Transaction::sale()
|
254 |
+
*/
|
255 |
+
public function sale($customerId, $transactionAttribs)
|
256 |
+
{
|
257 |
+
$this->_validateId($customerId);
|
258 |
+
return Braintree_Transaction::sale(
|
259 |
+
array_merge($transactionAttribs,
|
260 |
+
array('customerId' => $customerId)
|
261 |
+
)
|
262 |
+
);
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* create a new sale for a customer, assuming validations will pass
|
267 |
+
*
|
268 |
+
* returns a Braintree_Transaction object on success
|
269 |
+
* @access public
|
270 |
+
* @param string $customerId
|
271 |
+
* @param array $transactionAttribs
|
272 |
+
* @return object Braintree_Transaction
|
273 |
+
* @throws Braintree_Exception_ValidationsFailed
|
274 |
+
* @see Braintree_Transaction::sale()
|
275 |
+
*/
|
276 |
+
public function saleNoValidate($customerId, $transactionAttribs)
|
277 |
+
{
|
278 |
+
$result = $this->sale($customerId, $transactionAttribs);
|
279 |
+
return Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $result);
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Returns a ResourceCollection of customers matching the search query.
|
284 |
+
*
|
285 |
+
* If <b>query</b> is a string, the search will be a basic search.
|
286 |
+
* If <b>query</b> is a hash, the search will be an advanced search.
|
287 |
+
* For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/customer-api#searching http://www.braintreepaymentsolutions.com/gateway/customer-api}
|
288 |
+
*
|
289 |
+
* @param mixed $query search query
|
290 |
+
* @param array $options options such as page number
|
291 |
+
* @return object Braintree_ResourceCollection
|
292 |
+
* @throws InvalidArgumentException
|
293 |
+
*/
|
294 |
+
public function search($query)
|
295 |
+
{
|
296 |
+
$criteria = array();
|
297 |
+
foreach ($query as $term) {
|
298 |
+
$result = $term->toparam();
|
299 |
+
if(is_null($result) || empty($result)) {
|
300 |
+
throw new InvalidArgumentException('Operator must be provided');
|
301 |
+
}
|
302 |
+
|
303 |
+
$criteria[$term->name] = $term->toparam();
|
304 |
+
}
|
305 |
+
|
306 |
+
$path = $this->_config->merchantPath() . '/customers/advanced_search_ids';
|
307 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
308 |
+
$pager = array(
|
309 |
+
'object' => $this,
|
310 |
+
'method' => 'fetch',
|
311 |
+
'methodArgs' => array($query)
|
312 |
+
);
|
313 |
+
|
314 |
+
return new Braintree_ResourceCollection($response, $pager);
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* updates the customer record
|
319 |
+
*
|
320 |
+
* if calling this method in static context, customerId
|
321 |
+
* is the 2nd attribute. customerId is not sent in object context.
|
322 |
+
*
|
323 |
+
* @access public
|
324 |
+
* @param array $attributes
|
325 |
+
* @param string $customerId (optional)
|
326 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
327 |
+
*/
|
328 |
+
public function update($customerId, $attributes)
|
329 |
+
{
|
330 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
|
331 |
+
$this->_validateId($customerId);
|
332 |
+
return $this->_doUpdate(
|
333 |
+
'put',
|
334 |
+
'/customers/' . $customerId,
|
335 |
+
array('customer' => $attributes)
|
336 |
+
);
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* update a customer record, assuming validations will pass
|
341 |
+
*
|
342 |
+
* if calling this method in static context, customerId
|
343 |
+
* is the 2nd attribute. customerId is not sent in object context.
|
344 |
+
* returns a Braintree_Customer object on success
|
345 |
+
*
|
346 |
+
* @access public
|
347 |
+
* @param array $attributes
|
348 |
+
* @param string $customerId
|
349 |
+
* @return object Braintree_Customer
|
350 |
+
* @throws Braintree_Exception_ValidationsFailed
|
351 |
+
*/
|
352 |
+
public function updateNoValidate($customerId, $attributes)
|
353 |
+
{
|
354 |
+
$result = $this->update($customerId, $attributes);
|
355 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
356 |
+
}
|
357 |
+
/**
|
358 |
+
*
|
359 |
+
* @access public
|
360 |
+
* @param none
|
361 |
+
* @return string
|
362 |
+
*/
|
363 |
+
public function updateCustomerUrl()
|
364 |
+
{
|
365 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
|
366 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() .
|
367 |
+
'/customers/all/update_via_transparent_redirect_request';
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* update a customer from a TransparentRedirect operation
|
372 |
+
*
|
373 |
+
* @access public
|
374 |
+
* @param array $attribs
|
375 |
+
* @return object
|
376 |
+
*/
|
377 |
+
public function updateFromTransparentRedirect($queryString)
|
378 |
+
{
|
379 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
|
380 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
381 |
+
$queryString
|
382 |
+
);
|
383 |
+
return $this->_doUpdate(
|
384 |
+
'post',
|
385 |
+
'/customers/all/confirm_transparent_redirect_request',
|
386 |
+
array('id' => $params['id'])
|
387 |
+
);
|
388 |
+
}
|
389 |
+
|
390 |
+
/* instance methods */
|
391 |
+
|
392 |
+
/**
|
393 |
+
* sets instance properties from an array of values
|
394 |
+
*
|
395 |
+
* @ignore
|
396 |
+
* @access protected
|
397 |
+
* @param array $customerAttribs array of customer data
|
398 |
+
* @return none
|
399 |
+
*/
|
400 |
+
protected function _initialize($customerAttribs)
|
401 |
+
{
|
402 |
+
// set the attributes
|
403 |
+
$this->_attributes = $customerAttribs;
|
404 |
+
|
405 |
+
// map each address into its own object
|
406 |
+
$addressArray = array();
|
407 |
+
if (isset($customerAttribs['addresses'])) {
|
408 |
+
|
409 |
+
foreach ($customerAttribs['addresses'] AS $address) {
|
410 |
+
$addressArray[] = Braintree_Address::factory($address);
|
411 |
+
}
|
412 |
+
}
|
413 |
+
$this->_set('addresses', $addressArray);
|
414 |
+
|
415 |
+
// map each creditCard into its own object
|
416 |
+
$creditCardArray = array();
|
417 |
+
if (isset($customerAttribs['creditCards'])) {
|
418 |
+
foreach ($customerAttribs['creditCards'] AS $creditCard) {
|
419 |
+
$creditCardArray[] = Braintree_CreditCard::factory($creditCard);
|
420 |
+
}
|
421 |
+
}
|
422 |
+
$this->_set('creditCards', $creditCardArray);
|
423 |
+
|
424 |
+
// map each paypalAccount into its own object
|
425 |
+
$paypalAccountArray = array();
|
426 |
+
if (isset($customerAttribs['paypalAccounts'])) {
|
427 |
+
foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) {
|
428 |
+
$paypalAccountArray[] = Braintree_PayPalAccount::factory($paypalAccount);
|
429 |
+
}
|
430 |
+
}
|
431 |
+
$this->_set('paypalAccounts', $paypalAccountArray);
|
432 |
+
|
433 |
+
// map each applePayCard into its own object
|
434 |
+
$applePayCardArray = array();
|
435 |
+
if (isset($customerAttribs['applePayCards'])) {
|
436 |
+
foreach ($customerAttribs['applePayCards'] AS $applePayCard) {
|
437 |
+
$applePayCardArray[] = Braintree_applePayCard::factory($applePayCard);
|
438 |
+
}
|
439 |
+
}
|
440 |
+
$this->_set('applePayCards', $applePayCardArray);
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* returns a string representation of the customer
|
445 |
+
* @return string
|
446 |
+
*/
|
447 |
+
public function __toString()
|
448 |
+
{
|
449 |
+
return __CLASS__ . '[' .
|
450 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* returns false if comparing object is not a Braintree_Customer,
|
455 |
+
* or is a Braintree_Customer with a different id
|
456 |
+
*
|
457 |
+
* @param object $otherCust customer to compare against
|
458 |
+
* @return boolean
|
459 |
+
*/
|
460 |
+
public function isEqual($otherCust)
|
461 |
+
{
|
462 |
+
return !($otherCust instanceof Braintree_Customer) ? false : $this->id === $otherCust->id;
|
463 |
+
}
|
464 |
+
|
465 |
+
/**
|
466 |
+
* returns an array containt all of the customer's payment methods
|
467 |
+
*
|
468 |
+
* @return array
|
469 |
+
*/
|
470 |
+
public function paymentMethods()
|
471 |
+
{
|
472 |
+
return array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards);
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* returns the customer's default payment method
|
477 |
+
*
|
478 |
+
* @return object Braintree_CreditCard or Braintree_PayPalAccount
|
479 |
+
*/
|
480 |
+
public function defaultPaymentMethod()
|
481 |
+
{
|
482 |
+
$defaultPaymentMethods = array_filter($this->paymentMethods(), 'Braintree_Customer::_defaultPaymentMethodFilter');
|
483 |
+
return current($defaultPaymentMethods);
|
484 |
+
}
|
485 |
+
|
486 |
+
public static function _defaultPaymentMethodFilter($paymentMethod)
|
487 |
+
{
|
488 |
+
return $paymentMethod->isDefault();
|
489 |
+
}
|
490 |
+
|
491 |
+
/* private class properties */
|
492 |
+
|
493 |
+
/**
|
494 |
+
* @access protected
|
495 |
+
* @var array registry of customer data
|
496 |
+
*/
|
497 |
+
protected $_attributes = array(
|
498 |
+
'addresses' => '',
|
499 |
+
'company' => '',
|
500 |
+
'creditCards' => '',
|
501 |
+
'email' => '',
|
502 |
+
'fax' => '',
|
503 |
+
'firstName' => '',
|
504 |
+
'id' => '',
|
505 |
+
'lastName' => '',
|
506 |
+
'phone' => '',
|
507 |
+
'createdAt' => '',
|
508 |
+
'updatedAt' => '',
|
509 |
+
'website' => '',
|
510 |
+
);
|
511 |
+
|
512 |
+
/**
|
513 |
+
* sends the create request to the gateway
|
514 |
+
*
|
515 |
+
* @ignore
|
516 |
+
* @param string $subPath
|
517 |
+
* @param array $params
|
518 |
+
* @return mixed
|
519 |
+
*/
|
520 |
+
public function _doCreate($subPath, $params)
|
521 |
+
{
|
522 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
523 |
+
$response = $this->_http->post($fullPath, $params);
|
524 |
+
|
525 |
+
return $this->_verifyGatewayResponse($response);
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* verifies that a valid customer id is being used
|
530 |
+
* @ignore
|
531 |
+
* @param string customer id
|
532 |
+
* @throws InvalidArgumentException
|
533 |
+
*/
|
534 |
+
private function _validateId($id = null) {
|
535 |
+
if (empty($id)) {
|
536 |
+
throw new InvalidArgumentException(
|
537 |
+
'expected customer id to be set'
|
538 |
+
);
|
539 |
+
}
|
540 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
|
541 |
+
throw new InvalidArgumentException(
|
542 |
+
$id . ' is an invalid customer id.'
|
543 |
+
);
|
544 |
+
}
|
545 |
+
}
|
546 |
+
|
547 |
+
|
548 |
+
/* private class methods */
|
549 |
+
|
550 |
+
/**
|
551 |
+
* sends the update request to the gateway
|
552 |
+
*
|
553 |
+
* @ignore
|
554 |
+
* @param string $subPath
|
555 |
+
* @param array $params
|
556 |
+
* @return mixed
|
557 |
+
*/
|
558 |
+
private function _doUpdate($httpVerb, $subPath, $params)
|
559 |
+
{
|
560 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
561 |
+
$response = $this->_http->$httpVerb($fullPath, $params);
|
562 |
+
|
563 |
+
return $this->_verifyGatewayResponse($response);
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* generic method for validating incoming gateway responses
|
568 |
+
*
|
569 |
+
* creates a new Braintree_Customer object and encapsulates
|
570 |
+
* it inside a Braintree_Result_Successful object, or
|
571 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
572 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
573 |
+
*
|
574 |
+
* @ignore
|
575 |
+
* @param array $response gateway response values
|
576 |
+
* @return object Result_Successful or Result_Error
|
577 |
+
* @throws Braintree_Exception_Unexpected
|
578 |
+
*/
|
579 |
+
private function _verifyGatewayResponse($response)
|
580 |
+
{
|
581 |
+
if (isset($response['customer'])) {
|
582 |
+
// return a populated instance of Braintree_Customer
|
583 |
+
return new Braintree_Result_Successful(
|
584 |
+
Braintree_Customer::factory($response['customer'])
|
585 |
+
);
|
586 |
+
} else if (isset($response['apiErrorResponse'])) {
|
587 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
588 |
+
} else {
|
589 |
+
throw new Braintree_Exception_Unexpected(
|
590 |
+
"Expected customer or apiErrorResponse"
|
591 |
+
);
|
592 |
+
}
|
593 |
+
}
|
594 |
+
}
|
lib/Braintree/CustomerSearch.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_CustomerSearch
|
3 |
+
{
|
4 |
+
static function addressCountryName() { return new Braintree_TextNode('address_country_name'); }
|
5 |
+
static function addressExtendedAddress() { return new Braintree_TextNode('address_extended_address'); }
|
6 |
+
static function addressFirstName() { return new Braintree_TextNode('address_first_name'); }
|
7 |
+
static function addressLastName() { return new Braintree_TextNode('address_last_name'); }
|
8 |
+
static function addressLocality() { return new Braintree_TextNode('address_locality'); }
|
9 |
+
static function addressPostalCode() { return new Braintree_TextNode('address_postal_code'); }
|
10 |
+
static function addressRegion() { return new Braintree_TextNode('address_region'); }
|
11 |
+
static function addressStreetAddress() { return new Braintree_TextNode('address_street_address'); }
|
12 |
+
static function cardholderName() { return new Braintree_TextNode('cardholder_name'); }
|
13 |
+
static function company() { return new Braintree_TextNode('company'); }
|
14 |
+
static function email() { return new Braintree_TextNode('email'); }
|
15 |
+
static function fax() { return new Braintree_TextNode('fax'); }
|
16 |
+
static function firstName() { return new Braintree_TextNode('first_name'); }
|
17 |
+
static function id() { return new Braintree_TextNode('id'); }
|
18 |
+
static function lastName() { return new Braintree_TextNode('last_name'); }
|
19 |
+
static function paymentMethodToken() { return new Braintree_TextNode('payment_method_token'); }
|
20 |
+
static function paymentMethodTokenWithDuplicates() { return new Braintree_IsNode('payment_method_token_with_duplicates'); }
|
21 |
+
static function paypalAccountEmail() { return new Braintree_IsNode('paypal_account_email'); }
|
22 |
+
static function phone() { return new Braintree_TextNode('phone'); }
|
23 |
+
static function website() { return new Braintree_TextNode('website'); }
|
24 |
+
|
25 |
+
static function creditCardExpirationDate() { return new Braintree_EqualityNode('credit_card_expiration_date'); }
|
26 |
+
static function creditCardNumber() { return new Braintree_PartialMatchNode('credit_card_number'); }
|
27 |
+
|
28 |
+
static function ids() { return new Braintree_MultipleValueNode('ids'); }
|
29 |
+
|
30 |
+
static function createdAt() { return new Braintree_RangeNode("created_at"); }
|
31 |
+
}
|
lib/Braintree/Descriptor.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_Descriptor extends Braintree_Instance
|
3 |
+
{
|
4 |
+
}
|
lib/Braintree/Digest.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Digest encryption module
|
4 |
+
* Digest creates an HMAC-SHA1 hash for encrypting messages
|
5 |
+
*
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
*/
|
8 |
+
class Braintree_Digest
|
9 |
+
{
|
10 |
+
public static function hexDigestSha1($key, $string)
|
11 |
+
{
|
12 |
+
if(function_exists('hash_hmac')) {
|
13 |
+
return self::_builtInHmacSha1($string, $key);
|
14 |
+
} else {
|
15 |
+
return self::_hmacSha1($string, $key);
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function hexDigestSha256($key, $string)
|
20 |
+
{
|
21 |
+
return hash_hmac('sha256', $string, hash('sha256', $key, true));
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function secureCompare($left, $right)
|
25 |
+
{
|
26 |
+
if (strlen($left) != strlen($right)) {
|
27 |
+
return false;
|
28 |
+
}
|
29 |
+
|
30 |
+
$leftBytes = unpack("C*", $left);
|
31 |
+
$rightBytes = unpack("C*", $right);
|
32 |
+
|
33 |
+
$result = 0;
|
34 |
+
for ($i = 1; $i <= count($leftBytes); $i++) {
|
35 |
+
$result = $result | ($leftBytes[$i] ^ $rightBytes[$i]);
|
36 |
+
}
|
37 |
+
return $result == 0;
|
38 |
+
}
|
39 |
+
|
40 |
+
public static function _builtInHmacSha1($message, $key)
|
41 |
+
{
|
42 |
+
return hash_hmac('sha1', $message, sha1($key, true));
|
43 |
+
}
|
44 |
+
|
45 |
+
public static function _hmacSha1($message, $key)
|
46 |
+
{
|
47 |
+
$pack = 'H40';
|
48 |
+
$keyDigest = sha1($key,true);
|
49 |
+
$innerPad = str_repeat(chr(0x36), 64);
|
50 |
+
$outerPad = str_repeat(chr(0x5C), 64);
|
51 |
+
|
52 |
+
for ($i = 0; $i < 20; $i++) {
|
53 |
+
$innerPad{$i} = $keyDigest{$i} ^ $innerPad{$i};
|
54 |
+
$outerPad{$i} = $keyDigest{$i} ^ $outerPad{$i};
|
55 |
+
}
|
56 |
+
|
57 |
+
return sha1($outerPad.pack($pack, sha1($innerPad.$message)));
|
58 |
+
}
|
59 |
+
}
|
lib/Braintree/Disbursement.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
final class Braintree_Disbursement extends Braintree
|
3 |
+
{
|
4 |
+
private $_merchantAccount;
|
5 |
+
|
6 |
+
protected function _initialize($disbursementAttribs)
|
7 |
+
{
|
8 |
+
$this->_attributes = $disbursementAttribs;
|
9 |
+
$this->merchantAccountDetails = $disbursementAttribs['merchantAccount'];
|
10 |
+
|
11 |
+
if (isset($disbursementAttribs['merchantAccount'])) {
|
12 |
+
$this->_set('merchantAccount',
|
13 |
+
Braintree_MerchantAccount::factory($disbursementAttribs['merchantAccount'])
|
14 |
+
);
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
public function transactions()
|
19 |
+
{
|
20 |
+
$collection = Braintree_Transaction::search(array(
|
21 |
+
Braintree_TransactionSearch::ids()->in($this->transactionIds)
|
22 |
+
));
|
23 |
+
|
24 |
+
return $collection;
|
25 |
+
}
|
26 |
+
|
27 |
+
public static function factory($attributes)
|
28 |
+
{
|
29 |
+
$instance = new self();
|
30 |
+
$instance->_initialize($attributes);
|
31 |
+
return $instance;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function __toString()
|
35 |
+
{
|
36 |
+
$display = array(
|
37 |
+
'id', 'merchantAccountDetails', 'exceptionMessage', 'amount',
|
38 |
+
'disbursementDate', 'followUpAction', 'retry', 'success',
|
39 |
+
'transactionIds'
|
40 |
+
);
|
41 |
+
|
42 |
+
$displayAttributes = array();
|
43 |
+
foreach ($display AS $attrib) {
|
44 |
+
$displayAttributes[$attrib] = $this->$attrib;
|
45 |
+
}
|
46 |
+
return __CLASS__ . '[' .
|
47 |
+
Braintree_Util::attributesToString($displayAttributes) .']';
|
48 |
+
}
|
49 |
+
}
|
lib/Braintree/DisbursementDetails.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Disbursement details from a transaction
|
4 |
+
* Creates an instance of DisbursementDetails as returned from a transaction
|
5 |
+
*
|
6 |
+
*
|
7 |
+
* @package Braintree
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*
|
10 |
+
* @property-read string $settlementAmount
|
11 |
+
* @property-read string $settlementCurrencyIsoCode
|
12 |
+
* @property-read string $settlementCurrencyExchangeRate
|
13 |
+
* @property-read string $fundsHeld
|
14 |
+
* @property-read string $success
|
15 |
+
* @property-read string $disbursementDate
|
16 |
+
* @uses Braintree_Instance inherits methods
|
17 |
+
*/
|
18 |
+
class Braintree_DisbursementDetails extends Braintree_Instance
|
19 |
+
{
|
20 |
+
protected $_attributes = array();
|
21 |
+
|
22 |
+
function isValid() {
|
23 |
+
return !is_null($this->disbursementDate);
|
24 |
+
}
|
25 |
+
}
|
lib/Braintree/Discount.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_Discount extends Braintree_Modification
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self();
|
7 |
+
$instance->_initialize($attributes);
|
8 |
+
return $instance;
|
9 |
+
}
|
10 |
+
|
11 |
+
|
12 |
+
// static methods redirecting to gateway
|
13 |
+
|
14 |
+
public static function all()
|
15 |
+
{
|
16 |
+
return Braintree_Configuration::gateway()->discount()->all();
|
17 |
+
}
|
18 |
+
}
|
lib/Braintree/DiscountGateway.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_DiscountGateway
|
3 |
+
{
|
4 |
+
private $_gateway;
|
5 |
+
private $_config;
|
6 |
+
private $_http;
|
7 |
+
|
8 |
+
public function __construct($gateway)
|
9 |
+
{
|
10 |
+
$this->_gateway = $gateway;
|
11 |
+
$this->_config = $gateway->config;
|
12 |
+
$this->_http = new Braintree_Http($gateway->config);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function all()
|
16 |
+
{
|
17 |
+
$path = $this->_config->merchantPath() . '/discounts';
|
18 |
+
$response = $this->_http->get($path);
|
19 |
+
|
20 |
+
$discounts = array("discount" => $response['discounts']);
|
21 |
+
|
22 |
+
return Braintree_Util::extractAttributeAsArray(
|
23 |
+
$discounts,
|
24 |
+
'discount'
|
25 |
+
);
|
26 |
+
}
|
27 |
+
}
|
lib/Braintree/Dispute.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Creates an instance of Dispute as returned from a transaction
|
4 |
+
*
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*
|
9 |
+
* @property-read string $amount
|
10 |
+
* @property-read string $currencyIsoCode
|
11 |
+
* @property-read date $receivedDate
|
12 |
+
* @property-read string $reason
|
13 |
+
* @property-read string $status
|
14 |
+
* @property-read string $disbursementDate
|
15 |
+
* @property-read object $transactionDetails
|
16 |
+
*/
|
17 |
+
final class Braintree_Dispute extends Braintree
|
18 |
+
{
|
19 |
+
protected $_attributes = array();
|
20 |
+
|
21 |
+
/* Dispute Status */
|
22 |
+
const OPEN = 'open';
|
23 |
+
const WON = 'won';
|
24 |
+
const LOST = 'lost';
|
25 |
+
|
26 |
+
/* deprecated; for backwards compatibilty */
|
27 |
+
const Open = 'open';
|
28 |
+
|
29 |
+
/* Dispute Reason */
|
30 |
+
const CANCELLED_RECURRING_TRANSACTION = "cancelled_recurring_transaction";
|
31 |
+
const CREDIT_NOT_PROCESSED = "credit_not_processed";
|
32 |
+
const DUPLICATE = "duplicate";
|
33 |
+
const FRAUD = "fraud";
|
34 |
+
const GENERAL = "general";
|
35 |
+
const INVALID_ACCOUNT = "invalid_account";
|
36 |
+
const NOT_RECOGNIZED = "not_recognized";
|
37 |
+
const PRODUCT_NOT_RECEIVED = "product_not_received";
|
38 |
+
const PRODUCT_UNSATISFACTORY = "product_unsatisfactory";
|
39 |
+
const TRANSACTION_AMOUNT_DIFFERS = "transaction_amount_differs";
|
40 |
+
const RETRIEVAL = "retrieval";
|
41 |
+
|
42 |
+
|
43 |
+
protected function _initialize($disputeAttribs)
|
44 |
+
{
|
45 |
+
$this->_attributes = $disputeAttribs;
|
46 |
+
|
47 |
+
if (isset($disputeAttribs['transaction'])) {
|
48 |
+
$this->_set('transactionDetails',
|
49 |
+
new Braintree_Dispute_TransactionDetails($disputeAttribs['transaction'])
|
50 |
+
);
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
public static function factory($attributes)
|
55 |
+
{
|
56 |
+
$instance = new self();
|
57 |
+
$instance->_initialize($attributes);
|
58 |
+
return $instance;
|
59 |
+
}
|
60 |
+
|
61 |
+
public function __toString()
|
62 |
+
{
|
63 |
+
$display = array(
|
64 |
+
'amount', 'reason', 'status',
|
65 |
+
'replyByDate', 'receivedDate', 'currencyIsoCode'
|
66 |
+
);
|
67 |
+
|
68 |
+
$displayAttributes = array();
|
69 |
+
foreach ($display AS $attrib) {
|
70 |
+
$displayAttributes[$attrib] = $this->$attrib;
|
71 |
+
}
|
72 |
+
return __CLASS__ . '[' .
|
73 |
+
Braintree_Util::attributesToString($displayAttributes) .']';
|
74 |
+
}
|
75 |
+
}
|
lib/Braintree/Dispute/TransactionDetails.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Transaction details for a dispute
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @copyright 2010 Braintree Payment Solutions
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Creates an instance of DisbursementDetails as returned from a transaction
|
11 |
+
*
|
12 |
+
*
|
13 |
+
* @package Braintree
|
14 |
+
* @copyright 2010 Braintree Payment Solutions
|
15 |
+
*
|
16 |
+
* @property-read string $amount
|
17 |
+
* @property-read string $id
|
18 |
+
* @uses Braintree_Instance inherits methods
|
19 |
+
*/
|
20 |
+
class Braintree_Dispute_TransactionDetails extends Braintree_Instance
|
21 |
+
{
|
22 |
+
}
|
lib/Braintree/EqualityNode.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_EqualityNode extends Braintree_IsNode
|
4 |
+
{
|
5 |
+
function isNot($value)
|
6 |
+
{
|
7 |
+
$this->searchTerms['is_not'] = strval($value);
|
8 |
+
return $this;
|
9 |
+
}
|
10 |
+
}
|
lib/Braintree/Error/Codes.php
ADDED
@@ -0,0 +1,457 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* Validation Error codes and messages
|
5 |
+
*
|
6 |
+
* ErrorCodes class provides constants for validation errors.
|
7 |
+
* The constants should be used to check for a specific validation
|
8 |
+
* error in a ValidationErrorCollection.
|
9 |
+
* The error messages returned from the server may change;
|
10 |
+
* but the codes will remain the same.
|
11 |
+
*
|
12 |
+
* @package Braintree
|
13 |
+
* @subpackage Errors
|
14 |
+
* @category Validation
|
15 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
16 |
+
*/
|
17 |
+
class Braintree_Error_Codes
|
18 |
+
{
|
19 |
+
const ADDRESS_CANNOT_BE_BLANK = '81801';
|
20 |
+
const ADDRESS_COMPANY_IS_TOO_LONG = '81802';
|
21 |
+
const ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED = '91814';
|
22 |
+
const ADDRESS_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED = '91816';
|
23 |
+
const ADDRESS_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED = '91817';
|
24 |
+
const ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED = '91803';
|
25 |
+
const ADDRESS_EXTENDED_ADDRESS_IS_TOO_LONG = '81804';
|
26 |
+
const ADDRESS_FIRST_NAME_IS_TOO_LONG = '81805';
|
27 |
+
const ADDRESS_INCONSISTENT_COUNTRY = '91815';
|
28 |
+
const ADDRESS_LAST_NAME_IS_TOO_LONG = '81806';
|
29 |
+
const ADDRESS_LOCALITY_IS_TOO_LONG = '81807';
|
30 |
+
const ADDRESS_POSTAL_CODE_INVALID_CHARACTERS = '81813';
|
31 |
+
const ADDRESS_POSTAL_CODE_IS_REQUIRED = '81808';
|
32 |
+
const ADDRESS_POSTAL_CODE_IS_TOO_LONG = '81809';
|
33 |
+
const ADDRESS_REGION_IS_TOO_LONG = '81810';
|
34 |
+
const ADDRESS_STREET_ADDRESS_IS_REQUIRED = '81811';
|
35 |
+
const ADDRESS_STREET_ADDRESS_IS_TOO_LONG = '81812';
|
36 |
+
const ADDRESS_TOO_MANY_ADDRESSES_PER_CUSTOMER = '91818';
|
37 |
+
const ADDRESS_COMPANY_IS_INVALID = '91821';
|
38 |
+
const ADDRESS_REGION_IS_INVALID = '91825';
|
39 |
+
const ADDRESS_POSTAL_CODE_IS_INVALID = '91826';
|
40 |
+
const ADDRESS_LAST_NAME_IS_INVALID = '91820';
|
41 |
+
const ADDRESS_EXTENDED_ADDRESS_IS_INVALID = '91823';
|
42 |
+
const ADDRESS_STREET_ADDRESS_IS_INVALID = '91822';
|
43 |
+
const ADDRESS_LOCALITY_IS_INVALID = '91824';
|
44 |
+
const ADDRESS_FIRST_NAME_IS_INVALID = '91819';
|
45 |
+
|
46 |
+
const APPLE_PAY_CARDS_ARE_NOT_ACCEPTED = "83501";
|
47 |
+
const APPLE_PAY_CUSTOMER_ID_IS_REQUIRED_FOR_VAULTING = "83502";
|
48 |
+
const APPLE_PAY_TOKEN_IS_IN_USE = "93503";
|
49 |
+
const APPLE_PAY_PAYMENT_METHOD_NONCE_CONSUMED = "93504";
|
50 |
+
const APPLE_PAY_PAYMENT_METHOD_NONCE_UNKNOWN = "93505";
|
51 |
+
const APPLE_PAY_PAYMENT_METHOD_NONCE_UNLOCKED = "93506";
|
52 |
+
const APPLE_PAY_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = "83518";
|
53 |
+
const APPLE_PAY_CANNOT_UPDATE_APPLE_PAY_CARD_USING_PAYMENT_METHOD_NONCE = "93507";
|
54 |
+
const APPLE_PAY_NUMBER_IS_REQUIRED = "93508";
|
55 |
+
const APPLE_PAY_EXPIRATION_MONTH_IS_REQUIRED = "93509";
|
56 |
+
const APPLE_PAY_EXPIRATION_YEAR_IS_REQUIRED = "93510";
|
57 |
+
const APPLE_PAY_CRYPTOGRAM_IS_REQUIRED = "93511";
|
58 |
+
const APPLE_PAY_DECRYPTION_FAILED = "83512";
|
59 |
+
const APPLE_PAY_DISABLED = "93513";
|
60 |
+
const APPLE_PAY_MERCHANT_NOT_CONFIGURED = "93514";
|
61 |
+
const APPLE_PAY_MERCHANT_KEYS_ALREADY_CONFIGURED = "93515";
|
62 |
+
const APPLE_PAY_MERCHANT_KEYS_NOT_CONFIGURED = "93516";
|
63 |
+
const APPLE_PAY_CERTIFICATE_INVALID = "93517";
|
64 |
+
const APPLE_PAY_CERTIFICATE_MISMATCH = '93519';
|
65 |
+
const APPLE_PAY_INVALID_TOKEN = '83520';
|
66 |
+
const APPLE_PAY_PRIVATE_KEY_MISMATCH = '93521';
|
67 |
+
const APPLE_PAY_KEY_MISMATCH_STORING_CERTIFICATE = '93522';
|
68 |
+
|
69 |
+
const AUTHORIZATION_FINGERPRINT_INVALID_CREATED_AT = '93204';
|
70 |
+
const AUTHORIZATION_FINGERPRINT_INVALID_FORMAT = '93202';
|
71 |
+
const AUTHORIZATION_FINGERPRINT_INVALID_PUBLIC_KEY = '93205';
|
72 |
+
const AUTHORIZATION_FINGERPRINT_INVALID_SIGNATURE = '93206';
|
73 |
+
const AUTHORIZATION_FINGERPRINT_MISSING_FINGERPRINT = '93201';
|
74 |
+
const AUTHORIZATION_FINGERPRINT_OPTIONS_NOT_ALLOWED_WITHOUT_CUSTOMER = '93207';
|
75 |
+
const AUTHORIZATION_FINGERPRINT_SIGNATURE_REVOKED = '93203';
|
76 |
+
|
77 |
+
const CLIENT_TOKEN_CUSTOMER_DOES_NOT_EXIST = '92804';
|
78 |
+
const CLIENT_TOKEN_FAIL_ON_DUPLICATE_PAYMENT_METHOD_REQUIRES_CUSTOMER_ID = '92803';
|
79 |
+
const CLIENT_TOKEN_MAKE_DEFAULT_REQUIRES_CUSTOMER_ID = '92801';
|
80 |
+
const CLIENT_TOKEN_PROXY_MERCHANT_DOES_NOT_EXIST = '92805';
|
81 |
+
const CLIENT_TOKEN_UNSUPPORTED_VERSION = '92806';
|
82 |
+
const CLIENT_TOKEN_VERIFY_CARD_REQUIRES_CUSTOMER_ID = '92802';
|
83 |
+
const CLIENT_TOKEN_MERCHANT_ACCOUNT_DOES_NOT_EXIST = '92807';
|
84 |
+
|
85 |
+
const CREDIT_CARD_BILLING_ADDRESS_CONFLICT = '91701';
|
86 |
+
const CREDIT_CARD_BILLING_ADDRESS_ID_IS_INVALID = '91702';
|
87 |
+
const CREDIT_CARD_CANNOT_UPDATE_CARD_USING_PAYMENT_METHOD_NONCE = '91735';
|
88 |
+
const CREDIT_CARD_CARDHOLDER_NAME_IS_TOO_LONG = '81723';
|
89 |
+
const CREDIT_CARD_CREDIT_CARD_TYPE_IS_NOT_ACCEPTED = '81703';
|
90 |
+
const CREDIT_CARD_CREDIT_CARD_TYPE_IS_NOT_ACCEPTED_BY_SUBSCRIPTION_MERCHANT_ACCOUNT = '81718';
|
91 |
+
const CREDIT_CARD_CUSTOMER_ID_IS_INVALID = '91705';
|
92 |
+
const CREDIT_CARD_CUSTOMER_ID_IS_REQUIRED = '91704';
|
93 |
+
const CREDIT_CARD_CVV_IS_INVALID = '81707';
|
94 |
+
const CREDIT_CARD_CVV_IS_REQUIRED = '81706';
|
95 |
+
const CREDIT_CARD_CVV_VERIFICATION_FAILED = '81736';
|
96 |
+
const CREDIT_CARD_DUPLICATE_CARD_EXISTS = '81724';
|
97 |
+
const CREDIT_CARD_EXPIRATION_DATE_CONFLICT = '91708';
|
98 |
+
const CREDIT_CARD_EXPIRATION_DATE_IS_INVALID = '81710';
|
99 |
+
const CREDIT_CARD_EXPIRATION_DATE_IS_REQUIRED = '81709';
|
100 |
+
const CREDIT_CARD_EXPIRATION_DATE_YEAR_IS_INVALID = '81711';
|
101 |
+
const CREDIT_CARD_EXPIRATION_MONTH_IS_INVALID = '81712';
|
102 |
+
const CREDIT_CARD_EXPIRATION_YEAR_IS_INVALID = '81713';
|
103 |
+
const CREDIT_CARD_INVALID_VENMO_SDK_PAYMENT_METHOD_CODE = '91727';
|
104 |
+
const CREDIT_CARD_NUMBER_INVALID_LENGTH = '81716';
|
105 |
+
const CREDIT_CARD_NUMBER_IS_INVALID = '81715';
|
106 |
+
const CREDIT_CARD_NUMBER_IS_REQUIRED = '81714';
|
107 |
+
const CREDIT_CARD_NUMBER_LENGTH_IS_INVALID = '81716';
|
108 |
+
const CREDIT_CARD_NUMBER_MUST_BE_TEST_NUMBER = '81717';
|
109 |
+
const CREDIT_CARD_OPTIONS_UPDATE_EXISTING_TOKEN_IS_INVALID = '91723';
|
110 |
+
const CREDIT_CARD_OPTIONS_UPDATE_EXISTING_TOKEN_NOT_ALLOWED = '91729';
|
111 |
+
const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91728';
|
112 |
+
const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_CANNOT_BE_NEGATIVE = '91739';
|
113 |
+
const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_FORMAT_IS_INVALID = '91740';
|
114 |
+
const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_NOT_SUPPORTED_BY_PROCESSOR = '91741';
|
115 |
+
const CREDIT_CARD_PAYMENT_METHOD_CONFLICT = '81725';
|
116 |
+
const CREDIT_CARD_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91734';
|
117 |
+
const CREDIT_CARD_PAYMENT_METHOD_NONCE_CONSUMED = '91731';
|
118 |
+
const CREDIT_CARD_PAYMENT_METHOD_NONCE_LOCKED = '91733';
|
119 |
+
const CREDIT_CARD_PAYMENT_METHOD_NONCE_UNKNOWN = '91732';
|
120 |
+
const CREDIT_CARD_PAYMENT_METHOD_IS_NOT_A_CREDIT_CARD = '91738';
|
121 |
+
const CREDIT_CARD_POSTAL_CODE_VERIFICATION_FAILED = '81737';
|
122 |
+
const CREDIT_CARD_TOKEN_FORMAT_IS_INVALID = '91718';
|
123 |
+
const CREDIT_CARD_TOKEN_INVALID = '91718';
|
124 |
+
const CREDIT_CARD_TOKEN_IS_IN_USE = '91719';
|
125 |
+
const CREDIT_CARD_TOKEN_IS_NOT_ALLOWED = '91721';
|
126 |
+
const CREDIT_CARD_TOKEN_IS_REQUIRED = '91722';
|
127 |
+
const CREDIT_CARD_TOKEN_IS_TOO_LONG = '91720';
|
128 |
+
const CREDIT_CARD_VENMO_SDK_PAYMENT_METHOD_CODE_CARD_TYPE_IS_NOT_ACCEPTED = '91726';
|
129 |
+
const CREDIT_CARD_VERIFICATION_NOT_SUPPORTED_ON_THIS_MERCHANT_ACCOUNT = '91730';
|
130 |
+
|
131 |
+
const CUSTOMER_COMPANY_IS_TOO_LONG = '81601';
|
132 |
+
const CUSTOMER_CUSTOM_FIELD_IS_INVALID = '91602';
|
133 |
+
const CUSTOMER_CUSTOM_FIELD_IS_TOO_LONG = '81603';
|
134 |
+
const CUSTOMER_EMAIL_IS_INVALID = '81604';
|
135 |
+
const CUSTOMER_EMAIL_FORMAT_IS_INVALID = '81604';
|
136 |
+
const CUSTOMER_EMAIL_IS_REQUIRED = '81606';
|
137 |
+
const CUSTOMER_EMAIL_IS_TOO_LONG = '81605';
|
138 |
+
const CUSTOMER_FAX_IS_TOO_LONG = '81607';
|
139 |
+
const CUSTOMER_FIRST_NAME_IS_TOO_LONG = '81608';
|
140 |
+
const CUSTOMER_ID_IS_INVAILD = '91610'; //Deprecated
|
141 |
+
const CUSTOMER_ID_IS_INVALID = '91610';
|
142 |
+
const CUSTOMER_ID_IS_IN_USE = '91609';
|
143 |
+
const CUSTOMER_ID_IS_NOT_ALLOWED = '91611';
|
144 |
+
const CUSTOMER_ID_IS_REQUIRED = '91613';
|
145 |
+
const CUSTOMER_ID_IS_TOO_LONG = '91612';
|
146 |
+
const CUSTOMER_LAST_NAME_IS_TOO_LONG = '81613';
|
147 |
+
const CUSTOMER_PHONE_IS_TOO_LONG = '81614';
|
148 |
+
const CUSTOMER_WEBSITE_IS_INVALID = '81616';
|
149 |
+
const CUSTOMER_WEBSITE_FORMAT_IS_INVALID = '81616';
|
150 |
+
const CUSTOMER_WEBSITE_IS_TOO_LONG = '81615';
|
151 |
+
|
152 |
+
const DESCRIPTOR_NAME_FORMAT_IS_INVALID = '92201';
|
153 |
+
const DESCRIPTOR_PHONE_FORMAT_IS_INVALID = '92202';
|
154 |
+
const DESCRIPTOR_INTERNATIONAL_NAME_FORMAT_IS_INVALID = '92204';
|
155 |
+
const DESCRIPTOR_DYNAMIC_DESCRIPTORS_DISABLED = '92203';
|
156 |
+
const DESCRIPTOR_INTERNATIONAL_PHONE_FORMAT_IS_INVALID = '92205';
|
157 |
+
const DESCRIPTOR_URL_FORMAT_IS_INVALID = '92206';
|
158 |
+
|
159 |
+
const INDUSTRY_DATA_INDUSTRY_TYPE_IS_INVALID = '93401';
|
160 |
+
const INDUSTRY_DATA_LODGING_EMPTY_DATA = '93402';
|
161 |
+
const INDUSTRY_DATA_LODGING_FOLIO_NUMBER_IS_INVALID = '93403';
|
162 |
+
const INDUSTRY_DATA_LODGING_CHECK_IN_DATE_IS_INVALID = '93404';
|
163 |
+
const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_IS_INVALID = '93405';
|
164 |
+
const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_MUST_FOLLOW_CHECK_IN_DATE = '93406';
|
165 |
+
const INDUSTRY_DATA_LODGING_UNKNOWN_DATA_FIELD = '93407';
|
166 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_EMPTY_DATA = "93408";
|
167 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_UNKNOWN_DATA_FIELD = "93409";
|
168 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_TRAVEL_PACKAGE_IS_INVALID = "93410";
|
169 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_DEPARTURE_DATE_IS_INVALID = "93411";
|
170 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_IN_DATE_IS_INVALID = "93412";
|
171 |
+
const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_OUT_DATE_IS_INVALID = "93413";
|
172 |
+
|
173 |
+
const MERCHANT_ACCOUNT_ID_FORMAT_IS_INVALID = '82603';
|
174 |
+
const MERCHANT_ACCOUNT_ID_IS_IN_USE = '82604';
|
175 |
+
const MERCHANT_ACCOUNT_ID_IS_NOT_ALLOWED = '82605';
|
176 |
+
const MERCHANT_ACCOUNT_ID_IS_TOO_LONG = '82602';
|
177 |
+
const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_IS_INVALID = '82607';
|
178 |
+
const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_IS_REQUIRED = '82606';
|
179 |
+
const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_MUST_BE_ACTIVE = '82608';
|
180 |
+
const MERCHANT_ACCOUNT_TOS_ACCEPTED_IS_REQUIRED = '82610';
|
181 |
+
const MERCHANT_ACCOUNT_CANNOT_BE_UPDATED = '82674';
|
182 |
+
const MERCHANT_ACCOUNT_DECLINED = '82626';
|
183 |
+
const MERCHANT_ACCOUNT_DECLINED_MASTER_CARD_MATCH = '82622';
|
184 |
+
const MERCHANT_ACCOUNT_DECLINED_OFAC = '82621';
|
185 |
+
const MERCHANT_ACCOUNT_DECLINED_FAILED_KYC = '82623';
|
186 |
+
const MERCHANT_ACCOUNT_DECLINED_SSN_INVALID = '82624';
|
187 |
+
const MERCHANT_ACCOUNT_DECLINED_SSN_MATCHES_DECEASED = '82625';
|
188 |
+
const MERCHANT_ACCOUNT_ID_CANNOT_BE_UPDATED = '82675';
|
189 |
+
const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_CANNOT_BE_UPDATED = '82676';
|
190 |
+
|
191 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ACCOUNT_NUMBER_IS_REQUIRED = '82614';
|
192 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_COMPANY_NAME_IS_INVALID = '82631';
|
193 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_COMPANY_NAME_IS_REQUIRED_WITH_TAX_ID = '82633';
|
194 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DATE_OF_BIRTH_IS_REQUIRED = '82612';
|
195 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED = '82626'; // Keep for backwards compatibility
|
196 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_MASTER_CARD_MATCH = '82622'; // Keep for backwards compatibility
|
197 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_OFAC = '82621'; // Keep for backwards compatibility
|
198 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_FAILED_KYC = '82623'; // Keep for backwards compatibility
|
199 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_SSN_INVALID = '82624'; // Keep for backwards compatibility
|
200 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_SSN_MATCHES_DECEASED = '82625'; // Keep for backwards compatibility
|
201 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_EMAIL_ADDRESS_IS_INVALID = '82616';
|
202 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_FIRST_NAME_IS_INVALID = '82627';
|
203 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_FIRST_NAME_IS_REQUIRED = '82609';
|
204 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_LAST_NAME_IS_INVALID = '82628';
|
205 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_LAST_NAME_IS_REQUIRED = '82611';
|
206 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_PHONE_IS_INVALID = '82636';
|
207 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ROUTING_NUMBER_IS_INVALID = '82635';
|
208 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ROUTING_NUMBER_IS_REQUIRED = '82613';
|
209 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_SSN_IS_INVALID = '82615';
|
210 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_IS_INVALID = '82632';
|
211 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_IS_REQUIRED_WITH_COMPANY_NAME = '82634';
|
212 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DATE_OF_BIRTH_IS_INVALID = '82663';
|
213 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_REGION_IS_INVALID = '82664';
|
214 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_EMAIL_ADDRESS_IS_REQUIRED = '82665';
|
215 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ACCOUNT_NUMBER_IS_INVALID = '82670';
|
216 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_MUST_BE_BLANK = '82673';
|
217 |
+
|
218 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_LOCALITY_IS_REQUIRED = '82618';
|
219 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_POSTAL_CODE_IS_INVALID = '82630';
|
220 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_POSTAL_CODE_IS_REQUIRED = '82619';
|
221 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_REGION_IS_REQUIRED = '82620';
|
222 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_STREET_ADDRESS_IS_INVALID = '82629';
|
223 |
+
const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_STREET_ADDRESS_IS_REQUIRED = '82617';
|
224 |
+
|
225 |
+
const MERCHANT_ACCOUNT_BUSINESS_DBA_NAME_IS_INVALID = '82646';
|
226 |
+
const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_INVALID = '82647';
|
227 |
+
const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_REQUIRED_WITH_LEGAL_NAME = '82648';
|
228 |
+
const MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_REQUIRED_WITH_TAX_ID = '82669';
|
229 |
+
const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_MUST_BE_BLANK = '82672';
|
230 |
+
const MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_INVALID = '82677';
|
231 |
+
const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_REGION_IS_INVALID = '82684';
|
232 |
+
const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_STREET_ADDRESS_IS_INVALID = '82685';
|
233 |
+
const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_POSTAL_CODE_IS_INVALID = '82686';
|
234 |
+
|
235 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_REQUIRED = '82637';
|
236 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_REQUIRED = '82638';
|
237 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_DATE_OF_BIRTH_IS_REQUIRED = '82639';
|
238 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_SSN_IS_INVALID = '82642';
|
239 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_INVALID = '82643';
|
240 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_INVALID = '82644';
|
241 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_INVALID = '82645';
|
242 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_PHONE_IS_INVALID = '82656';
|
243 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_DATE_OF_BIRTH_IS_INVALID = '82666';
|
244 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_REQUIRED = '82667';
|
245 |
+
|
246 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_REQUIRED = '82657';
|
247 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_LOCALITY_IS_REQUIRED = '82658';
|
248 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_REQUIRED = '82659';
|
249 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_REQUIRED = '82660';
|
250 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_INVALID = '82661';
|
251 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_INVALID = '82662';
|
252 |
+
const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_INVALID = '82668';
|
253 |
+
|
254 |
+
const MERCHANT_ACCOUNT_FUNDING_ROUTING_NUMBER_IS_REQUIRED = '82640';
|
255 |
+
const MERCHANT_ACCOUNT_FUNDING_ACCOUNT_NUMBER_IS_REQUIRED = '82641';
|
256 |
+
const MERCHANT_ACCOUNT_FUNDING_ROUTING_NUMBER_IS_INVALID = '82649';
|
257 |
+
const MERCHANT_ACCOUNT_FUNDING_ACCOUNT_NUMBER_IS_INVALID = '82671';
|
258 |
+
const MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_REQUIRED = '82678';
|
259 |
+
const MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_INVALID = '82679';
|
260 |
+
const MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_REQUIRED = '82680';
|
261 |
+
const MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_INVALID = '82681';
|
262 |
+
const MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_REQUIRED = '82682';
|
263 |
+
const MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_INVALID = '82683';
|
264 |
+
|
265 |
+
const PAYMENT_METHOD_CANNOT_FORWARD_PAYMENT_METHOD_TYPE = '93106';
|
266 |
+
const PAYMENT_METHOD_CUSTOMER_ID_IS_INVALID = '93105';
|
267 |
+
const PAYMENT_METHOD_CUSTOMER_ID_IS_REQUIRED = '93104';
|
268 |
+
const PAYMENT_METHOD_NONCE_IS_INVALID = '93102';
|
269 |
+
const PAYMENT_METHOD_NONCE_IS_REQUIRED = '93103';
|
270 |
+
const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_CONSUMED = '93107';
|
271 |
+
const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_UNKNOWN = '93108';
|
272 |
+
const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_LOCKED = '93109';
|
273 |
+
const PAYMENT_METHOD_PAYMENT_METHOD_PARAMS_ARE_REQUIRED = '93101';
|
274 |
+
|
275 |
+
const PAYPAL_ACCOUNT_CANNOT_HAVE_BOTH_ACCESS_TOKEN_AND_CONSENT_CODE = '82903';
|
276 |
+
const PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT = '82902';
|
277 |
+
const PAYPAL_ACCOUNT_CONSENT_CODE_OR_ACCESS_TOKEN_IS_REQUIRED = '82901';
|
278 |
+
const PAYPAL_ACCOUNT_CUSTOMER_ID_IS_REQUIRED_FOR_VAULTING = '82905';
|
279 |
+
const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_CONSUMED = '92907';
|
280 |
+
const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_LOCKED = '92909';
|
281 |
+
const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_UNKNOWN = '92908';
|
282 |
+
const PAYPAL_ACCOUNT_PAYPAL_ACCOUNTS_ARE_NOT_ACCEPTED = '82904';
|
283 |
+
const PAYPAL_ACCOUNT_PAYPAL_COMMUNICATION_ERROR = '92910';
|
284 |
+
const PAYPAL_ACCOUNT_TOKEN_IS_IN_USE = '92906';
|
285 |
+
const PAYPAL_ACCOUNT_AUTH_EXPIRED = '92911';
|
286 |
+
const PAYPAL_ACCOUNT_CANNOT_HAVE_FUNDING_SOURCE_WITHOUT_ACCESS_TOKEN = '92912';
|
287 |
+
const PAYPAL_ACCOUNT_INVALID_FUNDING_SOURCE_SELECTION = '92913';
|
288 |
+
const PAYPAL_ACCOUNT_CANNOT_UPDATE_PAYPAL_ACCOUNT_USING_PAYMENT_METHOD_NONCE = '92914';
|
289 |
+
|
290 |
+
const SEPA_BANK_ACCOUNT_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '93003';
|
291 |
+
const SEPA_BANK_ACCOUNT_BIC_IS_REQUIRED = '93002';
|
292 |
+
const SEPA_BANK_ACCOUNT_IBAN_IS_REQUIRED = '93001';
|
293 |
+
|
294 |
+
const SEPA_MANDATE_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '83301';
|
295 |
+
const SEPA_MANDATE_BIC_INVALID_CHARACTER = '83306';
|
296 |
+
const SEPA_MANDATE_BIC_IS_REQUIRED = '83302';
|
297 |
+
const SEPA_MANDATE_BIC_LENGTH_IS_INVALID = '83307';
|
298 |
+
const SEPA_MANDATE_BIC_UNSUPPORTED_COUNTRY = '83308';
|
299 |
+
const SEPA_MANDATE_BILLING_ADDRESS_CONFLICT = '93311';
|
300 |
+
const SEPA_MANDATE_BILLING_ADDRESS_ID_IS_INVALID = '93312';
|
301 |
+
const SEPA_MANDATE_IBAN_INVALID_CHARACTER = '83305';
|
302 |
+
const SEPA_MANDATE_IBAN_INVALID_FORMAT = '83310';
|
303 |
+
const SEPA_MANDATE_IBAN_IS_REQUIRED = '83303';
|
304 |
+
const SEPA_MANDATE_IBAN_UNSUPPORTED_COUNTRY = '83309';
|
305 |
+
const SEPA_MANDATE_TYPE_IS_REQUIRED = '93304';
|
306 |
+
const SEPA_MANDATE_TYPE_IS_INVALID = '93313';
|
307 |
+
|
308 |
+
const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_INVALID = '82302';
|
309 |
+
const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_REQUIRED = '82301';
|
310 |
+
const SETTLEMENT_BATCH_SUMMARY_CUSTOM_FIELD_IS_INVALID = '82303';
|
311 |
+
|
312 |
+
const SUBSCRIPTION_BILLING_DAY_OF_MONTH_CANNOT_BE_UPDATED = '91918';
|
313 |
+
const SUBSCRIPTION_BILLING_DAY_OF_MONTH_IS_INVALID = '91914';
|
314 |
+
const SUBSCRIPTION_BILLING_DAY_OF_MONTH_MUST_BE_NUMERIC = '91913';
|
315 |
+
const SUBSCRIPTION_CANNOT_ADD_DUPLICATE_ADDON_OR_DISCOUNT = '91911';
|
316 |
+
const SUBSCRIPTION_CANNOT_EDIT_CANCELED_SUBSCRIPTION = '81901';
|
317 |
+
const SUBSCRIPTION_CANNOT_EDIT_EXPIRED_SUBSCRIPTION = '81910';
|
318 |
+
const SUBSCRIPTION_CANNOT_EDIT_PRICE_CHANGING_FIELDS_ON_PAST_DUE_SUBSCRIPTION = '91920';
|
319 |
+
const SUBSCRIPTION_FIRST_BILLING_DATE_CANNOT_BE_IN_THE_PAST = '91916';
|
320 |
+
const SUBSCRIPTION_FIRST_BILLING_DATE_CANNOT_BE_UPDATED = '91919';
|
321 |
+
const SUBSCRIPTION_FIRST_BILLING_DATE_IS_INVALID = '91915';
|
322 |
+
const SUBSCRIPTION_ID_IS_IN_USE = '81902';
|
323 |
+
const SUBSCRIPTION_INCONSISTENT_NUMBER_OF_BILLING_CYCLES = '91908';
|
324 |
+
const SUBSCRIPTION_INCONSISTENT_START_DATE = '91917';
|
325 |
+
const SUBSCRIPTION_INVALID_REQUEST_FORMAT = '91921';
|
326 |
+
const SUBSCRIPTION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91901';
|
327 |
+
const SUBSCRIPTION_MISMATCH_CURRENCY_ISO_CODE = '91923';
|
328 |
+
const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_CANNOT_BE_BLANK = '91912';
|
329 |
+
const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_IS_TOO_SMALL = '91909';
|
330 |
+
const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_MUST_BE_GREATER_THAN_ZERO = '91907';
|
331 |
+
const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_MUST_BE_NUMERIC = '91906';
|
332 |
+
const SUBSCRIPTION_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91924';
|
333 |
+
const SUBSCRIPTION_PAYMENT_METHOD_NONCE_IS_INVALID = '91925';
|
334 |
+
const SUBSCRIPTION_PAYMENT_METHOD_NONCE_NOT_ASSOCIATED_WITH_CUSTOMER = '91926';
|
335 |
+
const SUBSCRIPTION_PAYMENT_METHOD_NONCE_UNVAULTED_CARD_IS_NOT_ACCEPTED = '91927';
|
336 |
+
const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_CARD_TYPE_IS_NOT_ACCEPTED = '91902';
|
337 |
+
const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_IS_INVALID = '91903';
|
338 |
+
const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_NOT_ASSOCIATED_WITH_CUSTOMER = '91905';
|
339 |
+
const SUBSCRIPTION_PLAN_BILLING_FREQUENCY_CANNOT_BE_UPDATED = '91922';
|
340 |
+
const SUBSCRIPTION_PLAN_ID_IS_INVALID = '91904';
|
341 |
+
const SUBSCRIPTION_PRICE_CANNOT_BE_BLANK = '81903';
|
342 |
+
const SUBSCRIPTION_PRICE_FORMAT_IS_INVALID = '81904';
|
343 |
+
const SUBSCRIPTION_PRICE_IS_TOO_LARGE = '81923';
|
344 |
+
const SUBSCRIPTION_STATUS_IS_CANCELED = '81905';
|
345 |
+
const SUBSCRIPTION_TOKEN_FORMAT_IS_INVALID = '81906';
|
346 |
+
const SUBSCRIPTION_TRIAL_DURATION_FORMAT_IS_INVALID = '81907';
|
347 |
+
const SUBSCRIPTION_TRIAL_DURATION_IS_REQUIRED = '81908';
|
348 |
+
const SUBSCRIPTION_TRIAL_DURATION_UNIT_IS_INVALID = '81909';
|
349 |
+
|
350 |
+
const SUBSCRIPTION_MODIFICATION_AMOUNT_CANNOT_BE_BLANK = '92003';
|
351 |
+
const SUBSCRIPTION_MODIFICATION_AMOUNT_IS_INVALID = '92002';
|
352 |
+
const SUBSCRIPTION_MODIFICATION_AMOUNT_IS_TOO_LARGE = '92023';
|
353 |
+
const SUBSCRIPTION_MODIFICATION_CANNOT_EDIT_MODIFICATIONS_ON_PAST_DUE_SUBSCRIPTION = '92022';
|
354 |
+
const SUBSCRIPTION_MODIFICATION_CANNOT_UPDATE_AND_REMOVE = '92015';
|
355 |
+
const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_INCORRECT_KIND = '92020';
|
356 |
+
const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_INVALID = '92011';
|
357 |
+
const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_REQUIRED = '92012';
|
358 |
+
const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_INCORRECT_KIND = '92021';
|
359 |
+
const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_INVALID = '92025';
|
360 |
+
const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_NOT_PRESENT = '92016';
|
361 |
+
const SUBSCRIPTION_MODIFICATION_INCONSISTENT_NUMBER_OF_BILLING_CYCLES = '92018';
|
362 |
+
const SUBSCRIPTION_MODIFICATION_INHERITED_FROM_ID_IS_INVALID = '92013';
|
363 |
+
const SUBSCRIPTION_MODIFICATION_INHERITED_FROM_ID_IS_REQUIRED = '92014';
|
364 |
+
const SUBSCRIPTION_MODIFICATION_MISSING = '92024';
|
365 |
+
const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_CANNOT_BE_BLANK = '92017';
|
366 |
+
const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_IS_INVALID = '92005';
|
367 |
+
const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_MUST_BE_GREATER_THAN_ZERO = '92019';
|
368 |
+
const SUBSCRIPTION_MODIFICATION_QUANTITY_CANNOT_BE_BLANK = '92004';
|
369 |
+
const SUBSCRIPTION_MODIFICATION_QUANTITY_IS_INVALID = '92001';
|
370 |
+
const SUBSCRIPTION_MODIFICATION_QUANTITY_MUST_BE_GREATER_THAN_ZERO = '92010';
|
371 |
+
|
372 |
+
const TRANSACTION_AMOUNT_CANNOT_BE_NEGATIVE = '81501';
|
373 |
+
const TRANSACTION_AMOUNT_FORMAT_IS_INVALID = '81503';
|
374 |
+
const TRANSACTION_AMOUNT_IS_INVALID = '81503';
|
375 |
+
const TRANSACTION_AMOUNT_IS_REQUIRED = '81502';
|
376 |
+
const TRANSACTION_AMOUNT_IS_TOO_LARGE = '81528';
|
377 |
+
const TRANSACTION_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '81531';
|
378 |
+
const TRANSACTION_BILLING_ADDRESS_CONFLICT = '91530';
|
379 |
+
const TRANSACTION_CANNOT_BE_VOIDED = '91504';
|
380 |
+
const TRANSACTION_CANNOT_CLONE_CREDIT = '91543';
|
381 |
+
const TRANSACTION_CANNOT_CLONE_TRANSACTION_WITH_PAYPAL_ACCOUNT = '91573';
|
382 |
+
const TRANSACTION_CANNOT_CLONE_TRANSACTION_WITH_VAULT_CREDIT_CARD = '91540';
|
383 |
+
const TRANSACTION_CANNOT_CLONE_UNSUCCESSFUL_TRANSACTION = '91542';
|
384 |
+
const TRANSACTION_CANNOT_CLONE_VOICE_AUTHORIZATIONS = '91541';
|
385 |
+
const TRANSACTION_CANNOT_HOLD_IN_ESCROW = '91560';
|
386 |
+
const TRANSACTION_CANNOT_PARTIALLY_REFUND_ESCROWED_TRANSACTION = '91563';
|
387 |
+
const TRANSACTION_CANNOT_REFUND_CREDIT = '91505';
|
388 |
+
const TRANSACTION_CANNOT_REFUND_SETTLING_TRANSACTION = '91574';
|
389 |
+
const TRANSACTION_CANNOT_REFUND_UNLESS_SETTLED = '91506';
|
390 |
+
const TRANSACTION_CANNOT_REFUND_WITH_PENDING_MERCHANT_ACCOUNT = '91559';
|
391 |
+
const TRANSACTION_CANNOT_REFUND_WITH_SUSPENDED_MERCHANT_ACCOUNT = '91538';
|
392 |
+
const TRANSACTION_CANNOT_CANCEL_RELEASE = '91562';
|
393 |
+
const TRANSACTION_CANNOT_RELEASE_FROM_ESCROW = '91561';
|
394 |
+
const TRANSACTION_CANNOT_SUBMIT_FOR_SETTLEMENT = '91507';
|
395 |
+
const TRANSACTION_CANNOT_SIMULATE_SETTLEMENT = '91575';
|
396 |
+
const TRANSACTION_CHANNEL_IS_TOO_LONG = '91550';
|
397 |
+
const TRANSACTION_CREDIT_CARD_IS_REQUIRED = '91508';
|
398 |
+
const TRANSACTION_CUSTOMER_DEFAULT_PAYMENT_METHOD_CARD_TYPE_IS_NOT_ACCEPTED = '81509';
|
399 |
+
const TRANSACTION_CUSTOMER_DOES_NOT_HAVE_CREDIT_CARD = '91511';
|
400 |
+
const TRANSACTION_CUSTOMER_ID_IS_INVALID = '91510';
|
401 |
+
const TRANSACTION_CUSTOM_FIELD_IS_INVALID = '91526';
|
402 |
+
const TRANSACTION_CUSTOM_FIELD_IS_TOO_LONG = '81527';
|
403 |
+
const TRANSACTION_HAS_ALREADY_BEEN_REFUNDED = '91512';
|
404 |
+
const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_MOTO = '91558';
|
405 |
+
const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_REFUNDS = '91547';
|
406 |
+
const TRANSACTION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91513';
|
407 |
+
const TRANSACTION_MERCHANT_ACCOUNT_IS_SUSPENDED = '91514';
|
408 |
+
const TRANSACTION_MERCHANT_ACCOUNT_NAME_IS_INVALID = '91513'; //Deprecated
|
409 |
+
const TRANSACTION_OPTIONS_SUBMIT_FOR_SETTLEMENT_IS_REQUIRED_FOR_CLONING = '91544';
|
410 |
+
const TRANSACTION_OPTIONS_USE_BILLING_FOR_SHIPPING_DISABLED = '91572';
|
411 |
+
const TRANSACTION_OPTIONS_VAULT_IS_DISABLED = '91525';
|
412 |
+
const TRANSACTION_OPTIONS_PAY_PAL_CUSTOM_FIELD_TOO_LONG = '91580';
|
413 |
+
const TRANSACTION_ORDER_ID_IS_TOO_LONG = '91501';
|
414 |
+
const TRANSACTION_PAYMENT_INSTRUMENT_NOT_SUPPORTED_BY_MERCHANT_ACCOUNT = '91577';
|
415 |
+
const TRANSACTION_PAYMENT_METHOD_CONFLICT = '91515';
|
416 |
+
const TRANSACTION_PAYMENT_METHOD_CONFLICT_WITH_VENMO_SDK = '91549';
|
417 |
+
const TRANSACTION_PAYMENT_METHOD_DOES_NOT_BELONG_TO_CUSTOMER = '91516';
|
418 |
+
const TRANSACTION_PAYMENT_METHOD_DOES_NOT_BELONG_TO_SUBSCRIPTION = '91527';
|
419 |
+
const TRANSACTION_PAYMENT_METHOD_NONCE_CONSUMED = '91564';
|
420 |
+
const TRANSACTION_PAYMENT_METHOD_NONCE_UNKNOWN = '91565';
|
421 |
+
const TRANSACTION_PAYMENT_METHOD_NONCE_LOCKED = '91566';
|
422 |
+
const TRANSACTION_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91567';
|
423 |
+
const TRANSACTION_PAYMENT_METHOD_TOKEN_CARD_TYPE_IS_NOT_ACCEPTED = '91517';
|
424 |
+
const TRANSACTION_PAYMENT_METHOD_TOKEN_IS_INVALID = '91518';
|
425 |
+
const TRANSACTION_PAYPAL_NOT_ENABLED = '91576';
|
426 |
+
const TRANSACTION_PAY_PAL_AUTH_EXPIRED = '91579';
|
427 |
+
const TRANSACTION_PROCESSOR_AUTHORIZATION_CODE_CANNOT_BE_SET = '91519';
|
428 |
+
const TRANSACTION_PROCESSOR_AUTHORIZATION_CODE_IS_INVALID = '81520';
|
429 |
+
const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_CREDITS = '91546';
|
430 |
+
const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_VOICE_AUTHORIZATIONS = '91545';
|
431 |
+
const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_INVALID = '91548';
|
432 |
+
const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_TOO_LONG = '91537';
|
433 |
+
const TRANSACTION_REFUND_AMOUNT_IS_TOO_LARGE = '91521';
|
434 |
+
const TRANSACTION_SERVICE_FEE_AMOUNT_CANNOT_BE_NEGATIVE = '91554';
|
435 |
+
const TRANSACTION_SERVICE_FEE_AMOUNT_FORMAT_IS_INVALID = '91555';
|
436 |
+
const TRANSACTION_SERVICE_FEE_AMOUNT_IS_TOO_LARGE = '91556';
|
437 |
+
const TRANSACTION_SERVICE_FEE_AMOUNT_NOT_ALLOWED_ON_MASTER_MERCHANT_ACCOUNT = '91557';
|
438 |
+
const TRANSACTION_SERVICE_FEE_IS_NOT_ALLOWED_ON_CREDITS = '91552';
|
439 |
+
const TRANSACTION_SERVICE_FEE_NOT_ACCEPTED_FOR_PAYPAL = '91578';
|
440 |
+
const TRANSACTION_SETTLEMENT_AMOUNT_IS_LESS_THAN_SERVICE_FEE_AMOUNT = '91551';
|
441 |
+
const TRANSACTION_SETTLEMENT_AMOUNT_IS_TOO_LARGE = '91522';
|
442 |
+
const TRANSACTION_SHIPPING_ADDRESS_DOESNT_MATCH_CUSTOMER = '91581';
|
443 |
+
const TRANSACTION_SUBSCRIPTION_DOES_NOT_BELONG_TO_CUSTOMER = '91529';
|
444 |
+
const TRANSACTION_SUBSCRIPTION_ID_IS_INVALID = '91528';
|
445 |
+
const TRANSACTION_SUBSCRIPTION_STATUS_MUST_BE_PAST_DUE = '91531';
|
446 |
+
const TRANSACTION_SUB_MERCHANT_ACCOUNT_REQUIRES_SERVICE_FEE_AMOUNT = '91553';
|
447 |
+
const TRANSACTION_TAX_AMOUNT_CANNOT_BE_NEGATIVE = '81534';
|
448 |
+
const TRANSACTION_TAX_AMOUNT_FORMAT_IS_INVALID = '81535';
|
449 |
+
const TRANSACTION_TAX_AMOUNT_IS_TOO_LARGE = '81536';
|
450 |
+
|
451 |
+
const TRANSACTION_THREE_D_SECURE_AUTHENTICATION_FAILED = '81571';
|
452 |
+
const TRANSACTION_THREE_D_SECURE_TOKEN_IS_INVALID = '91568';
|
453 |
+
const TRANSACTION_THREE_D_SECURE_TRANSACTION_DATA_DOESNT_MATCH_VERIFY = '91570';
|
454 |
+
const TRANSACTION_TYPE_IS_INVALID = '91523';
|
455 |
+
const TRANSACTION_TYPE_IS_REQUIRED = '91524';
|
456 |
+
const TRANSACTION_UNSUPPORTED_VOICE_AUTHORIZATION = '91539';
|
457 |
+
}
|
lib/Braintree/Error/ErrorCollection.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* Error handler
|
5 |
+
* Handles validation errors
|
6 |
+
*
|
7 |
+
* Contains a read-only property $error which is a ValidationErrorCollection
|
8 |
+
*
|
9 |
+
* @package Braintree
|
10 |
+
* @subpackage Errors
|
11 |
+
* @category Errors
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*
|
14 |
+
* @property-read object $errors
|
15 |
+
*/
|
16 |
+
class Braintree_Error_ErrorCollection
|
17 |
+
{
|
18 |
+
private $_errors;
|
19 |
+
|
20 |
+
public function __construct($errorData)
|
21 |
+
{
|
22 |
+
$this->_errors =
|
23 |
+
new Braintree_Error_ValidationErrorCollection($errorData);
|
24 |
+
}
|
25 |
+
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Returns all of the validation errors at all levels of nesting in a single, flat array.
|
29 |
+
*/
|
30 |
+
public function deepAll()
|
31 |
+
{
|
32 |
+
return $this->_errors->deepAll();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Returns the total number of validation errors at all levels of nesting. For example,
|
37 |
+
*if creating a customer with a credit card and a billing address, and each of the customer,
|
38 |
+
* credit card, and billing address has 1 error, this method will return 3.
|
39 |
+
*
|
40 |
+
* @return int size
|
41 |
+
*/
|
42 |
+
public function deepSize()
|
43 |
+
{
|
44 |
+
$size = $this->_errors->deepSize();
|
45 |
+
return $size;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* return errors for the passed key name
|
50 |
+
*
|
51 |
+
* @param string $key
|
52 |
+
* @return mixed
|
53 |
+
*/
|
54 |
+
public function forKey($key)
|
55 |
+
{
|
56 |
+
return $this->_errors->forKey($key);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* return errors for the passed html field.
|
61 |
+
* For example, $result->errors->onHtmlField("transaction[customer][last_name]")
|
62 |
+
*
|
63 |
+
* @param string $field
|
64 |
+
* @return array
|
65 |
+
*/
|
66 |
+
public function onHtmlField($field)
|
67 |
+
{
|
68 |
+
$pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY);
|
69 |
+
$errors = $this;
|
70 |
+
foreach(array_slice($pieces, 0, -1) as $key) {
|
71 |
+
$errors = $errors->forKey(Braintree_Util::delimiterToCamelCase($key));
|
72 |
+
if (!isset($errors)) { return array(); }
|
73 |
+
}
|
74 |
+
$finalKey = Braintree_Util::delimiterToCamelCase(end($pieces));
|
75 |
+
return $errors->onAttribute($finalKey);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Returns the errors at the given nesting level (see forKey) in a single, flat array:
|
80 |
+
*
|
81 |
+
* <code>
|
82 |
+
* $result = Braintree_Customer::create(...);
|
83 |
+
* $customerErrors = $result->errors->forKey('customer')->shallowAll();
|
84 |
+
* </code>
|
85 |
+
*/
|
86 |
+
public function shallowAll()
|
87 |
+
{
|
88 |
+
return $this->_errors->shallowAll();
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
*
|
93 |
+
* @ignore
|
94 |
+
*/
|
95 |
+
public function __get($name)
|
96 |
+
{
|
97 |
+
$varName = "_$name";
|
98 |
+
return isset($this->$varName) ? $this->$varName : null;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
*
|
103 |
+
* @ignore
|
104 |
+
*/
|
105 |
+
public function __toString()
|
106 |
+
{
|
107 |
+
return sprintf('%s', $this->_errors);
|
108 |
+
}
|
109 |
+
}
|
lib/Braintree/Error/Validation.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* error object returned as part of a validation error collection
|
4 |
+
* provides read-only access to $attribute, $code, and $message
|
5 |
+
*
|
6 |
+
* <b>== More information ==</b>
|
7 |
+
*
|
8 |
+
* For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors}
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @subpackage Error
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*
|
14 |
+
* @property-read string $attribute
|
15 |
+
* @property-read string $code
|
16 |
+
* @property-read string $message
|
17 |
+
*/
|
18 |
+
class Braintree_Error_Validation
|
19 |
+
{
|
20 |
+
private $_attribute;
|
21 |
+
private $_code;
|
22 |
+
private $_message;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @ignore
|
26 |
+
* @param array $attributes
|
27 |
+
*/
|
28 |
+
public function __construct($attributes)
|
29 |
+
{
|
30 |
+
$this->_initializeFromArray($attributes);
|
31 |
+
}
|
32 |
+
/**
|
33 |
+
* initializes instance properties from the keys/values of an array
|
34 |
+
* @ignore
|
35 |
+
* @access protected
|
36 |
+
* @param array $attributes array of properties to set - single level
|
37 |
+
* @return none
|
38 |
+
*/
|
39 |
+
private function _initializeFromArray($attributes)
|
40 |
+
{
|
41 |
+
foreach($attributes AS $name => $value) {
|
42 |
+
$varName = "_$name";
|
43 |
+
$this->$varName = Braintree_Util::delimiterToCamelCase($value, '_');
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
*
|
49 |
+
* @ignore
|
50 |
+
*/
|
51 |
+
public function __get($name)
|
52 |
+
{
|
53 |
+
$varName = "_$name";
|
54 |
+
return isset($this->$varName) ? $this->$varName : null;
|
55 |
+
}
|
56 |
+
}
|
lib/Braintree/Error/ValidationErrorCollection.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* collection of errors enumerating all validation errors for a given request
|
4 |
+
*
|
5 |
+
* <b>== More information ==</b>
|
6 |
+
*
|
7 |
+
* For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors}
|
8 |
+
*
|
9 |
+
* @package Braintree
|
10 |
+
* @subpackage Error
|
11 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
12 |
+
*
|
13 |
+
* @property-read array $errors
|
14 |
+
* @property-read array $nested
|
15 |
+
*/
|
16 |
+
class Braintree_Error_ValidationErrorCollection extends Braintree_Collection
|
17 |
+
{
|
18 |
+
private $_errors = array();
|
19 |
+
private $_nested = array();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @ignore
|
23 |
+
*/
|
24 |
+
public function __construct($data)
|
25 |
+
{
|
26 |
+
foreach($data AS $key => $errorData)
|
27 |
+
// map errors to new collections recursively
|
28 |
+
if ($key == 'errors') {
|
29 |
+
foreach ($errorData AS $error) {
|
30 |
+
$this->_errors[] = new Braintree_Error_Validation($error);
|
31 |
+
}
|
32 |
+
} else {
|
33 |
+
$this->_nested[$key] = new Braintree_Error_ValidationErrorCollection($errorData);
|
34 |
+
}
|
35 |
+
|
36 |
+
}
|
37 |
+
|
38 |
+
public function deepAll()
|
39 |
+
{
|
40 |
+
$validationErrors = array_merge(array(), $this->_errors);
|
41 |
+
foreach($this->_nested as $nestedErrors)
|
42 |
+
{
|
43 |
+
$validationErrors = array_merge($validationErrors, $nestedErrors->deepAll());
|
44 |
+
}
|
45 |
+
return $validationErrors;
|
46 |
+
}
|
47 |
+
|
48 |
+
public function deepSize()
|
49 |
+
{
|
50 |
+
$total = sizeof($this->_errors);
|
51 |
+
foreach($this->_nested as $_nestedErrors)
|
52 |
+
{
|
53 |
+
$total = $total + $_nestedErrors->deepSize();
|
54 |
+
}
|
55 |
+
return $total;
|
56 |
+
}
|
57 |
+
|
58 |
+
public function forIndex($index)
|
59 |
+
{
|
60 |
+
return $this->forKey("index" . $index);
|
61 |
+
}
|
62 |
+
|
63 |
+
public function forKey($key)
|
64 |
+
{
|
65 |
+
return isset($this->_nested[$key]) ? $this->_nested[$key] : null;
|
66 |
+
}
|
67 |
+
|
68 |
+
public function onAttribute($attribute)
|
69 |
+
{
|
70 |
+
$matches = array();
|
71 |
+
foreach ($this->_errors AS $key => $error) {
|
72 |
+
if($error->attribute == $attribute) {
|
73 |
+
$matches[] = $error;
|
74 |
+
}
|
75 |
+
}
|
76 |
+
return $matches;
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
public function shallowAll()
|
81 |
+
{
|
82 |
+
return $this->_errors;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
*
|
87 |
+
* @ignore
|
88 |
+
*/
|
89 |
+
public function __get($name)
|
90 |
+
{
|
91 |
+
$varName = "_$name";
|
92 |
+
return isset($this->$varName) ? $this->$varName : null;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @ignore
|
97 |
+
*/
|
98 |
+
public function __toString()
|
99 |
+
{
|
100 |
+
$output = array();
|
101 |
+
|
102 |
+
// TODO: implement scope
|
103 |
+
if (!empty($this->_errors)) {
|
104 |
+
$output[] = $this->_inspect($this->_errors);
|
105 |
+
}
|
106 |
+
if (!empty($this->_nested)) {
|
107 |
+
foreach ($this->_nested AS $key => $values) {
|
108 |
+
$output[] = $this->_inspect($this->_nested);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
return join(', ', $output);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @ignore
|
116 |
+
*/
|
117 |
+
private function _inspect($errors, $scope = null)
|
118 |
+
{
|
119 |
+
$eOutput = '[' . __CLASS__ . '/errors:[';
|
120 |
+
foreach($errors AS $error => $errorObj) {
|
121 |
+
$outputErrs[] = "({$errorObj->error['code']} {$errorObj->error['message']})";
|
122 |
+
}
|
123 |
+
$eOutput .= join(', ', $outputErrs) . ']]';
|
124 |
+
|
125 |
+
return $eOutput;
|
126 |
+
}
|
127 |
+
}
|
lib/Braintree/Exception.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* super class for all Braintree exceptions
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception extends Exception
|
10 |
+
{
|
11 |
+
}
|
lib/Braintree/Exception/Authentication.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when authentication fails.
|
4 |
+
* This may be caused by an incorrect Braintree_Configuration
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Exception
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*/
|
10 |
+
class Braintree_Exception_Authentication extends Braintree_Exception
|
11 |
+
{
|
12 |
+
|
13 |
+
}
|
lib/Braintree/Exception/Authorization.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when authorization fails
|
4 |
+
* Raised when the API key being used is not authorized to perform
|
5 |
+
* the attempted action according to the roles assigned to the user
|
6 |
+
* who owns the API key.
|
7 |
+
*
|
8 |
+
* @package Braintree
|
9 |
+
* @subpackage Exception
|
10 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
11 |
+
*/
|
12 |
+
class Braintree_Exception_Authorization extends Braintree_Exception
|
13 |
+
{
|
14 |
+
|
15 |
+
}
|
lib/Braintree/Exception/Configuration.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when the Braintree library is not completely configured.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @see Braintree_Configuration
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_Configuration extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/DownForMaintenance.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when the gateway is down for maintenance.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_DownForMaintenance extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/ForgedQueryString.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when a suspected forged query string is present
|
4 |
+
* Raised from methods that confirm transparent redirect requests
|
5 |
+
* when the given query string cannot be verified. This may indicate
|
6 |
+
* an attempted hack on the merchant's transparent redirect
|
7 |
+
* confirmation URL.
|
8 |
+
*
|
9 |
+
* @package Braintree
|
10 |
+
* @subpackage Exception
|
11 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
12 |
+
*/
|
13 |
+
class Braintree_Exception_ForgedQueryString extends Braintree_Exception
|
14 |
+
{
|
15 |
+
|
16 |
+
}
|
lib/Braintree/Exception/InvalidSignature.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_Exception_InvalidSignature extends Braintree_Exception
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
lib/Braintree/Exception/NotFound.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when a record could not be found.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_NotFound extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/SSLCaFileNotFound.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when the SSL CaFile is not found.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_SSLCaFileNotFound extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/SSLCertificate.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when the SSL certificate fails verification.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_SSLCertificate extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/ServerError.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when an unexpected server error occurs.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_ServerError extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/Unexpected.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when an error occurs that the client library is not built to handle.
|
4 |
+
* This shouldn't happen.
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Exception
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*/
|
10 |
+
class Braintree_Exception_Unexpected extends Braintree_Exception
|
11 |
+
{
|
12 |
+
|
13 |
+
}
|
lib/Braintree/Exception/UpgradeRequired.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised when a client library must be upgraded.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_UpgradeRequired extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Exception/ValidationsFailed.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Raised from non-validating methods when gateway validations fail.
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Exception
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Exception_ValidationsFailed extends Braintree_Exception
|
10 |
+
{
|
11 |
+
|
12 |
+
}
|
lib/Braintree/Gateway.php
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Gateway module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Gateway
|
10 |
+
{
|
11 |
+
public $config;
|
12 |
+
|
13 |
+
public function __construct($config)
|
14 |
+
{
|
15 |
+
if (is_array($config)) {
|
16 |
+
$config = new Braintree_Configuration($config);
|
17 |
+
}
|
18 |
+
$config->assertValid();
|
19 |
+
$this->config = $config;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function customer()
|
23 |
+
{
|
24 |
+
return new Braintree_CustomerGateway($this);
|
25 |
+
}
|
26 |
+
|
27 |
+
public function addOn()
|
28 |
+
{
|
29 |
+
return new Braintree_AddOnGateway($this);
|
30 |
+
}
|
31 |
+
|
32 |
+
public function address()
|
33 |
+
{
|
34 |
+
return new Braintree_AddressGateway($this);
|
35 |
+
}
|
36 |
+
|
37 |
+
public function clientToken()
|
38 |
+
{
|
39 |
+
return new Braintree_ClientTokenGateway($this);
|
40 |
+
}
|
41 |
+
|
42 |
+
public function creditCard()
|
43 |
+
{
|
44 |
+
return new Braintree_CreditCardGateway($this);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function creditCardVerification()
|
48 |
+
{
|
49 |
+
return new Braintree_CreditCardVerificationGateway($this);
|
50 |
+
}
|
51 |
+
|
52 |
+
public function discount()
|
53 |
+
{
|
54 |
+
return new Braintree_DiscountGateway($this);
|
55 |
+
}
|
56 |
+
|
57 |
+
public function merchantAccount()
|
58 |
+
{
|
59 |
+
return new Braintree_MerchantAccountGateway($this);
|
60 |
+
}
|
61 |
+
|
62 |
+
public function paymentMethod()
|
63 |
+
{
|
64 |
+
return new Braintree_PaymentMethodGateway($this);
|
65 |
+
}
|
66 |
+
|
67 |
+
public function paymentMethodNonce()
|
68 |
+
{
|
69 |
+
return new Braintree_PaymentMethodNonceGateway($this);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function payPalAccount()
|
73 |
+
{
|
74 |
+
return new Braintree_PayPalAccountGateway($this);
|
75 |
+
}
|
76 |
+
|
77 |
+
public function plan()
|
78 |
+
{
|
79 |
+
return new Braintree_PlanGateway($this);
|
80 |
+
}
|
81 |
+
|
82 |
+
public function settlementBatchSummary()
|
83 |
+
{
|
84 |
+
return new Braintree_SettlementBatchSummaryGateway($this);
|
85 |
+
}
|
86 |
+
|
87 |
+
public function subscription()
|
88 |
+
{
|
89 |
+
return new Braintree_SubscriptionGateway($this);
|
90 |
+
}
|
91 |
+
|
92 |
+
public function transaction()
|
93 |
+
{
|
94 |
+
return new Braintree_TransactionGateway($this);
|
95 |
+
}
|
96 |
+
|
97 |
+
public function transparentRedirect()
|
98 |
+
{
|
99 |
+
return new Braintree_TransparentRedirectGateway($this);
|
100 |
+
}
|
101 |
+
}
|
lib/Braintree/Http.php
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree HTTP Client
|
4 |
+
* processes Http requests using curl
|
5 |
+
*
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
*/
|
8 |
+
class Braintree_Http
|
9 |
+
{
|
10 |
+
protected $_config;
|
11 |
+
|
12 |
+
public function __construct($config)
|
13 |
+
{
|
14 |
+
$this->_config = $config;
|
15 |
+
}
|
16 |
+
|
17 |
+
public function delete($path)
|
18 |
+
{
|
19 |
+
$response = $this->_doRequest('DELETE', $path);
|
20 |
+
if($response['status'] === 200) {
|
21 |
+
return true;
|
22 |
+
} else {
|
23 |
+
Braintree_Util::throwStatusCodeException($response['status']);
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
public function get($path)
|
28 |
+
{
|
29 |
+
$response = $this->_doRequest('GET', $path);
|
30 |
+
if($response['status'] === 200) {
|
31 |
+
return Braintree_Xml::buildArrayFromXml($response['body']);
|
32 |
+
} else {
|
33 |
+
Braintree_Util::throwStatusCodeException($response['status']);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function post($path, $params = null)
|
38 |
+
{
|
39 |
+
$response = $this->_doRequest('POST', $path, $this->_buildXml($params));
|
40 |
+
$responseCode = $response['status'];
|
41 |
+
if($responseCode === 200 || $responseCode === 201 || $responseCode === 422) {
|
42 |
+
return Braintree_Xml::buildArrayFromXml($response['body']);
|
43 |
+
} else {
|
44 |
+
Braintree_Util::throwStatusCodeException($responseCode);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
public function put($path, $params = null)
|
49 |
+
{
|
50 |
+
$response = $this->_doRequest('PUT', $path, $this->_buildXml($params));
|
51 |
+
$responseCode = $response['status'];
|
52 |
+
if($responseCode === 200 || $responseCode === 201 || $responseCode === 422) {
|
53 |
+
return Braintree_Xml::buildArrayFromXml($response['body']);
|
54 |
+
} else {
|
55 |
+
Braintree_Util::throwStatusCodeException($responseCode);
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
private function _buildXml($params)
|
60 |
+
{
|
61 |
+
return empty($params) ? null : Braintree_Xml::buildXmlFromArray($params);
|
62 |
+
}
|
63 |
+
|
64 |
+
private function _doRequest($httpVerb, $path, $requestBody = null)
|
65 |
+
{
|
66 |
+
return $this->_doUrlRequest($httpVerb, $this->_config->baseUrl() . $path, $requestBody);
|
67 |
+
}
|
68 |
+
|
69 |
+
public function _doUrlRequest($httpVerb, $url, $requestBody = null)
|
70 |
+
{
|
71 |
+
$curl = curl_init();
|
72 |
+
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
|
73 |
+
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb);
|
74 |
+
curl_setopt($curl, CURLOPT_URL, $url);
|
75 |
+
curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
|
76 |
+
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
|
77 |
+
'Accept: application/xml',
|
78 |
+
'Content-Type: application/xml',
|
79 |
+
'User-Agent: Braintree PHP Library ' . Braintree_Version::get(),
|
80 |
+
'X-ApiVersion: ' . Braintree_Configuration::API_VERSION
|
81 |
+
));
|
82 |
+
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
83 |
+
curl_setopt($curl, CURLOPT_USERPWD, $this->_config->getPublicKey() . ':' . $this->_config->getPrivateKey());
|
84 |
+
// curl_setopt($curl, CURLOPT_VERBOSE, true);
|
85 |
+
if ($this->_config->sslOn()) {
|
86 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
|
87 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
|
88 |
+
curl_setopt($curl, CURLOPT_CAINFO, $this->_config->caFile());
|
89 |
+
}
|
90 |
+
|
91 |
+
if(!empty($requestBody)) {
|
92 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
|
93 |
+
}
|
94 |
+
|
95 |
+
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
96 |
+
$response = curl_exec($curl);
|
97 |
+
$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
98 |
+
curl_close($curl);
|
99 |
+
if ($this->_config->sslOn()) {
|
100 |
+
if ($httpStatus == 0) {
|
101 |
+
throw new Braintree_Exception_SSLCertificate();
|
102 |
+
}
|
103 |
+
}
|
104 |
+
return array('status' => $httpStatus, 'body' => $response);
|
105 |
+
}
|
106 |
+
}
|
lib/Braintree/Instance.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Class Instance template
|
4 |
+
* @package Braintree
|
5 |
+
* @subpackage Utility
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
* @abstract
|
8 |
+
*/
|
9 |
+
abstract class Braintree_Instance
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
*
|
13 |
+
* @param array $aAttribs
|
14 |
+
*/
|
15 |
+
public function __construct($attributes)
|
16 |
+
{
|
17 |
+
if (!empty($attributes)) {
|
18 |
+
$this->_initializeFromArray($attributes);
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* returns private/nonexistent instance properties
|
25 |
+
* @access public
|
26 |
+
* @param var $name property name
|
27 |
+
* @return mixed contents of instance properties
|
28 |
+
*/
|
29 |
+
public function __get($name)
|
30 |
+
{
|
31 |
+
if (array_key_exists($name, $this->_attributes)) {
|
32 |
+
return $this->_attributes[$name];
|
33 |
+
} else {
|
34 |
+
trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE);
|
35 |
+
return null;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* used by isset() and empty()
|
41 |
+
* @access public
|
42 |
+
* @param string $name property name
|
43 |
+
* @return boolean
|
44 |
+
*/
|
45 |
+
public function __isset($name)
|
46 |
+
{
|
47 |
+
return array_key_exists($name, $this->_attributes);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* create a printable representation of the object as:
|
52 |
+
* ClassName[property=value, property=value]
|
53 |
+
* @return var
|
54 |
+
*/
|
55 |
+
public function __toString()
|
56 |
+
{
|
57 |
+
$objOutput = Braintree_Util::implodeAssociativeArray($this->_attributes);
|
58 |
+
return get_class($this) .'['.$objOutput.']';
|
59 |
+
}
|
60 |
+
/**
|
61 |
+
* initializes instance properties from the keys/values of an array
|
62 |
+
* @ignore
|
63 |
+
* @access protected
|
64 |
+
* @param <type> $aAttribs array of properties to set - single level
|
65 |
+
* @return none
|
66 |
+
*/
|
67 |
+
private function _initializeFromArray($attributes)
|
68 |
+
{
|
69 |
+
$this->_attributes = $attributes;
|
70 |
+
}
|
71 |
+
|
72 |
+
}
|
lib/Braintree/IsNode.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_IsNode
|
4 |
+
{
|
5 |
+
function __construct($name)
|
6 |
+
{
|
7 |
+
$this->name = $name;
|
8 |
+
$this->searchTerms = array();
|
9 |
+
}
|
10 |
+
|
11 |
+
function is($value)
|
12 |
+
{
|
13 |
+
$this->searchTerms['is'] = strval($value);
|
14 |
+
return $this;
|
15 |
+
}
|
16 |
+
|
17 |
+
function toParam()
|
18 |
+
{
|
19 |
+
return $this->searchTerms;
|
20 |
+
}
|
21 |
+
}
|
lib/Braintree/KeyValueNode.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_KeyValueNode
|
4 |
+
{
|
5 |
+
function __construct($name)
|
6 |
+
{
|
7 |
+
$this->name = $name;
|
8 |
+
$this->searchTerm = True;
|
9 |
+
|
10 |
+
}
|
11 |
+
|
12 |
+
function is($value)
|
13 |
+
{
|
14 |
+
$this->searchTerm = $value;
|
15 |
+
return $this;
|
16 |
+
}
|
17 |
+
|
18 |
+
function toParam()
|
19 |
+
{
|
20 |
+
return $this->searchTerm;
|
21 |
+
}
|
22 |
+
}
|
lib/Braintree/MerchantAccount.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccount extends Braintree
|
4 |
+
{
|
5 |
+
const STATUS_ACTIVE = 'active';
|
6 |
+
const STATUS_PENDING = 'pending';
|
7 |
+
const STATUS_SUSPENDED = 'suspended';
|
8 |
+
|
9 |
+
const FUNDING_DESTINATION_BANK = 'bank';
|
10 |
+
const FUNDING_DESTINATION_EMAIL = 'email';
|
11 |
+
const FUNDING_DESTINATION_MOBILE_PHONE = 'mobile_phone';
|
12 |
+
|
13 |
+
public static function factory($attributes)
|
14 |
+
{
|
15 |
+
$instance = new self();
|
16 |
+
$instance->_initialize($attributes);
|
17 |
+
return $instance;
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function _initialize($merchantAccountAttribs)
|
21 |
+
{
|
22 |
+
$this->_attributes = $merchantAccountAttribs;
|
23 |
+
|
24 |
+
if (isset($merchantAccountAttribs['individual'])) {
|
25 |
+
$individual = $merchantAccountAttribs['individual'];
|
26 |
+
$this->_set('individualDetails', Braintree_MerchantAccount_IndividualDetails::Factory($individual));
|
27 |
+
}
|
28 |
+
|
29 |
+
if (isset($merchantAccountAttribs['business'])) {
|
30 |
+
$business = $merchantAccountAttribs['business'];
|
31 |
+
$this->_set('businessDetails', Braintree_MerchantAccount_BusinessDetails::Factory($business));
|
32 |
+
}
|
33 |
+
|
34 |
+
if (isset($merchantAccountAttribs['funding'])) {
|
35 |
+
$funding = $merchantAccountAttribs['funding'];
|
36 |
+
$this->_set('fundingDetails', new Braintree_MerchantAccount_FundingDetails($funding));
|
37 |
+
}
|
38 |
+
|
39 |
+
if (isset($merchantAccountAttribs['masterMerchantAccount'])) {
|
40 |
+
$masterMerchantAccount = $merchantAccountAttribs['masterMerchantAccount'];
|
41 |
+
$this->_set('masterMerchantAccount', Braintree_MerchantAccount::Factory($masterMerchantAccount));
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
// static methods redirecting to gateway
|
47 |
+
|
48 |
+
public static function create($attribs)
|
49 |
+
{
|
50 |
+
return Braintree_Configuration::gateway()->merchantAccount()->create($attribs);
|
51 |
+
}
|
52 |
+
|
53 |
+
public static function find($merchant_account_id)
|
54 |
+
{
|
55 |
+
return Braintree_Configuration::gateway()->merchantAccount()->find($merchant_account_id);
|
56 |
+
}
|
57 |
+
|
58 |
+
public static function update($merchant_account_id, $attributes)
|
59 |
+
{
|
60 |
+
return Braintree_Configuration::gateway()->merchantAccount()->update($merchant_account_id, $attributes);
|
61 |
+
}
|
62 |
+
}
|
lib/Braintree/MerchantAccount/AddressDetails.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccount_AddressDetails extends Braintree_Instance {
|
4 |
+
protected $_attributes = array();
|
5 |
+
}
|
lib/Braintree/MerchantAccount/BusinessDetails.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccount_BusinessDetails extends Braintree
|
4 |
+
{
|
5 |
+
protected function _initialize($businessAttribs)
|
6 |
+
{
|
7 |
+
$this->_attributes = $businessAttribs;
|
8 |
+
if (isset($businessAttribs['address'])) {
|
9 |
+
$this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($businessAttribs['address']));
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
public static function factory($attributes)
|
14 |
+
{
|
15 |
+
$instance = new self();
|
16 |
+
$instance->_initialize($attributes);
|
17 |
+
return $instance;
|
18 |
+
}
|
19 |
+
}
|
lib/Braintree/MerchantAccount/FundingDetails.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccount_FundingDetails extends Braintree_Instance
|
4 |
+
{
|
5 |
+
protected $_attributes = array();
|
6 |
+
}
|
lib/Braintree/MerchantAccount/IndividualDetails.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccount_IndividualDetails extends Braintree
|
4 |
+
{
|
5 |
+
protected function _initialize($individualAttribs)
|
6 |
+
{
|
7 |
+
$this->_attributes = $individualAttribs;
|
8 |
+
if (isset($individualAttribs['address'])) {
|
9 |
+
$this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($individualAttribs['address']));
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
public static function factory($attributes)
|
14 |
+
{
|
15 |
+
$instance = new self();
|
16 |
+
$instance->_initialize($attributes);
|
17 |
+
return $instance;
|
18 |
+
}
|
19 |
+
}
|
lib/Braintree/MerchantAccountGateway.php
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_MerchantAccountGateway
|
4 |
+
{
|
5 |
+
private $_gateway;
|
6 |
+
private $_config;
|
7 |
+
private $_http;
|
8 |
+
|
9 |
+
public function __construct($gateway)
|
10 |
+
{
|
11 |
+
$this->_gateway = $gateway;
|
12 |
+
$this->_config = $gateway->config;
|
13 |
+
$this->_http = new Braintree_Http($gateway->config);
|
14 |
+
}
|
15 |
+
|
16 |
+
public function create($attribs)
|
17 |
+
{
|
18 |
+
Braintree_Util::verifyKeys(self::detectSignature($attribs), $attribs);
|
19 |
+
return $this->_doCreate('/merchant_accounts/create_via_api', array('merchant_account' => $attribs));
|
20 |
+
}
|
21 |
+
|
22 |
+
public function find($merchant_account_id)
|
23 |
+
{
|
24 |
+
try {
|
25 |
+
$path = $this->_config->merchantPath() . '/merchant_accounts/' . $merchant_account_id;
|
26 |
+
$response = $this->_http->get($path);
|
27 |
+
return Braintree_MerchantAccount::factory($response['merchantAccount']);
|
28 |
+
} catch (Braintree_Exception_NotFound $e) {
|
29 |
+
throw new Braintree_Exception_NotFound('merchant account with id ' . $merchant_account_id . ' not found');
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
public function update($merchant_account_id, $attributes)
|
34 |
+
{
|
35 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
|
36 |
+
return $this->_doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', array('merchant_account' => $attributes));
|
37 |
+
}
|
38 |
+
|
39 |
+
public static function detectSignature($attribs)
|
40 |
+
{
|
41 |
+
if (isset($attribs['applicantDetails'])) {
|
42 |
+
trigger_error("DEPRECATED: Passing applicantDetails to create is deprecated. Please use individual, business, and funding", E_USER_NOTICE);
|
43 |
+
return self::createDeprecatedSignature();
|
44 |
+
} else {
|
45 |
+
return self::createSignature();
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
public static function updateSignature()
|
50 |
+
{
|
51 |
+
$signature = self::createSignature();
|
52 |
+
unset($signature['tosAccepted']);
|
53 |
+
return $signature;
|
54 |
+
}
|
55 |
+
|
56 |
+
public static function createSignature()
|
57 |
+
{
|
58 |
+
$addressSignature = array('streetAddress', 'postalCode', 'locality', 'region');
|
59 |
+
$individualSignature = array(
|
60 |
+
'firstName',
|
61 |
+
'lastName',
|
62 |
+
'email',
|
63 |
+
'phone',
|
64 |
+
'dateOfBirth',
|
65 |
+
'ssn',
|
66 |
+
array('address' => $addressSignature)
|
67 |
+
);
|
68 |
+
|
69 |
+
$businessSignature = array(
|
70 |
+
'dbaName',
|
71 |
+
'legalName',
|
72 |
+
'taxId',
|
73 |
+
array('address' => $addressSignature)
|
74 |
+
);
|
75 |
+
|
76 |
+
$fundingSignature = array(
|
77 |
+
'routingNumber',
|
78 |
+
'accountNumber',
|
79 |
+
'destination',
|
80 |
+
'email',
|
81 |
+
'mobilePhone',
|
82 |
+
'descriptor',
|
83 |
+
);
|
84 |
+
|
85 |
+
return array(
|
86 |
+
'id',
|
87 |
+
'tosAccepted',
|
88 |
+
'masterMerchantAccountId',
|
89 |
+
array('individual' => $individualSignature),
|
90 |
+
array('funding' => $fundingSignature),
|
91 |
+
array('business' => $businessSignature)
|
92 |
+
);
|
93 |
+
}
|
94 |
+
|
95 |
+
public static function createDeprecatedSignature()
|
96 |
+
{
|
97 |
+
$applicantDetailsAddressSignature = array('streetAddress', 'postalCode', 'locality', 'region');
|
98 |
+
$applicantDetailsSignature = array(
|
99 |
+
'companyName',
|
100 |
+
'firstName',
|
101 |
+
'lastName',
|
102 |
+
'email',
|
103 |
+
'phone',
|
104 |
+
'dateOfBirth',
|
105 |
+
'ssn',
|
106 |
+
'taxId',
|
107 |
+
'routingNumber',
|
108 |
+
'accountNumber',
|
109 |
+
array('address' => $applicantDetailsAddressSignature)
|
110 |
+
);
|
111 |
+
|
112 |
+
return array(
|
113 |
+
array('applicantDetails' => $applicantDetailsSignature),
|
114 |
+
'id',
|
115 |
+
'tosAccepted',
|
116 |
+
'masterMerchantAccountId'
|
117 |
+
);
|
118 |
+
}
|
119 |
+
|
120 |
+
public function _doCreate($subPath, $params)
|
121 |
+
{
|
122 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
123 |
+
$response = $this->_http->post($fullPath, $params);
|
124 |
+
|
125 |
+
return $this->_verifyGatewayResponse($response);
|
126 |
+
}
|
127 |
+
|
128 |
+
private function _doUpdate($subPath, $params)
|
129 |
+
{
|
130 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
131 |
+
$response = $this->_http->put($fullPath, $params);
|
132 |
+
|
133 |
+
return $this->_verifyGatewayResponse($response);
|
134 |
+
}
|
135 |
+
|
136 |
+
private function _verifyGatewayResponse($response)
|
137 |
+
{
|
138 |
+
if (isset($response['merchantAccount'])) {
|
139 |
+
// return a populated instance of Braintree_merchantAccount
|
140 |
+
return new Braintree_Result_Successful(
|
141 |
+
Braintree_MerchantAccount::factory($response['merchantAccount'])
|
142 |
+
);
|
143 |
+
} else if (isset($response['apiErrorResponse'])) {
|
144 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
145 |
+
} else {
|
146 |
+
throw new Braintree_Exception_Unexpected(
|
147 |
+
"Expected merchant account or apiErrorResponse"
|
148 |
+
);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
}
|
lib/Braintree/Modification.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_Modification extends Braintree
|
3 |
+
{
|
4 |
+
protected function _initialize($attributes)
|
5 |
+
{
|
6 |
+
$this->_attributes = $attributes;
|
7 |
+
|
8 |
+
$addOnArray = array();
|
9 |
+
if (isset($attributes['addOns'])) {
|
10 |
+
foreach ($attributes['addOns'] AS $addOn) {
|
11 |
+
$addOnArray[] = Braintree_addOn::factory($addOn);
|
12 |
+
}
|
13 |
+
}
|
14 |
+
$this->_attributes['addOns'] = $addOnArray;
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function factory($attributes)
|
18 |
+
{
|
19 |
+
$instance = new self();
|
20 |
+
$instance->_initialize($attributes);
|
21 |
+
return $instance;
|
22 |
+
}
|
23 |
+
}
|
lib/Braintree/MultipleValueNode.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_MultipleValueNode
|
4 |
+
{
|
5 |
+
function __construct($name, $allowedValues = array())
|
6 |
+
{
|
7 |
+
$this->name = $name;
|
8 |
+
$this->items = array();
|
9 |
+
$this->allowedValues = $allowedValues;
|
10 |
+
}
|
11 |
+
|
12 |
+
function in($values)
|
13 |
+
{
|
14 |
+
$bad_values = array_diff($values, $this->allowedValues);
|
15 |
+
if (count($this->allowedValues) > 0 && count($bad_values) > 0) {
|
16 |
+
$message = 'Invalid argument(s) for ' . $this->name . ':';
|
17 |
+
foreach ($bad_values AS $bad_value) {
|
18 |
+
$message .= ' ' . $bad_value;
|
19 |
+
}
|
20 |
+
|
21 |
+
throw new InvalidArgumentException($message);
|
22 |
+
}
|
23 |
+
|
24 |
+
$this->items = $values;
|
25 |
+
return $this;
|
26 |
+
}
|
27 |
+
|
28 |
+
function is($value)
|
29 |
+
{
|
30 |
+
return $this->in(array($value));
|
31 |
+
}
|
32 |
+
|
33 |
+
function toParam()
|
34 |
+
{
|
35 |
+
return $this->items;
|
36 |
+
}
|
37 |
+
}
|
lib/Braintree/MultipleValueOrTextNode.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_MultipleValueOrTextNode extends Braintree_MultipleValueNode
|
4 |
+
{
|
5 |
+
function __construct($name)
|
6 |
+
{
|
7 |
+
parent::__construct($name);
|
8 |
+
$this->textNode = new Braintree_TextNode($name);
|
9 |
+
}
|
10 |
+
|
11 |
+
function contains($value)
|
12 |
+
{
|
13 |
+
$this->textNode->contains($value);
|
14 |
+
return $this;
|
15 |
+
}
|
16 |
+
|
17 |
+
function endsWith($value)
|
18 |
+
{
|
19 |
+
$this->textNode->endsWith($value);
|
20 |
+
return $this;
|
21 |
+
}
|
22 |
+
|
23 |
+
function is($value)
|
24 |
+
{
|
25 |
+
$this->textNode->is($value);
|
26 |
+
return $this;
|
27 |
+
}
|
28 |
+
|
29 |
+
function isNot($value)
|
30 |
+
{
|
31 |
+
$this->textNode->isNot($value);
|
32 |
+
return $this;
|
33 |
+
}
|
34 |
+
|
35 |
+
function startsWith($value)
|
36 |
+
{
|
37 |
+
$this->textNode->startsWith($value);
|
38 |
+
return $this;
|
39 |
+
}
|
40 |
+
|
41 |
+
function toParam()
|
42 |
+
{
|
43 |
+
return array_merge(parent::toParam(), $this->textNode->toParam());
|
44 |
+
}
|
45 |
+
}
|
lib/Braintree/PartialMatchNode.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_PartialMatchNode extends Braintree_EqualityNode
|
4 |
+
{
|
5 |
+
function startsWith($value)
|
6 |
+
{
|
7 |
+
$this->searchTerms["starts_with"] = strval($value);
|
8 |
+
return $this;
|
9 |
+
}
|
10 |
+
|
11 |
+
function endsWith($value)
|
12 |
+
{
|
13 |
+
$this->searchTerms["ends_with"] = strval($value);
|
14 |
+
return $this;
|
15 |
+
}
|
16 |
+
}
|
lib/Braintree/PartnerMerchant.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Partner Merchant information that is generated when a partner is connected
|
4 |
+
* to or disconnected from a user.
|
5 |
+
*
|
6 |
+
* Creates an instance of PartnerMerchants
|
7 |
+
*
|
8 |
+
* @package Braintree
|
9 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
10 |
+
*
|
11 |
+
* @property-read string $merchantPublicId
|
12 |
+
* @property-read string $publicKey
|
13 |
+
* @property-read string $privateKey
|
14 |
+
* @property-read string $clientSideEncryptionKey
|
15 |
+
* @property-read string $partnerMerchantId
|
16 |
+
* @uses Braintree_Instance inherits methods
|
17 |
+
*/
|
18 |
+
class Braintree_PartnerMerchant extends Braintree
|
19 |
+
{
|
20 |
+
protected $_attributes = array();
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @ignore
|
24 |
+
*/
|
25 |
+
public static function factory($attributes)
|
26 |
+
{
|
27 |
+
$instance = new self();
|
28 |
+
$instance->_initialize($attributes);
|
29 |
+
|
30 |
+
return $instance;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @ignore
|
35 |
+
*/
|
36 |
+
protected function _initialize($attributes)
|
37 |
+
{
|
38 |
+
$this->_attributes = $attributes;
|
39 |
+
}
|
40 |
+
}
|
lib/Braintree/PayPalAccount.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PayPalAccount module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Manages Braintree PayPalAccounts
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
* @property-read string $email
|
21 |
+
* @property-read string $token
|
22 |
+
* @property-read string $imageUrl
|
23 |
+
*/
|
24 |
+
class Braintree_PayPalAccount extends Braintree
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* factory method: returns an instance of Braintree_PayPalAccount
|
28 |
+
* to the requesting method, with populated properties
|
29 |
+
*
|
30 |
+
* @ignore
|
31 |
+
* @return object instance of Braintree_PayPalAccount
|
32 |
+
*/
|
33 |
+
public static function factory($attributes)
|
34 |
+
{
|
35 |
+
$instance = new self();
|
36 |
+
$instance->_initialize($attributes);
|
37 |
+
return $instance;
|
38 |
+
}
|
39 |
+
|
40 |
+
/* instance methods */
|
41 |
+
|
42 |
+
/**
|
43 |
+
* returns false if default is null or false
|
44 |
+
*
|
45 |
+
* @return boolean
|
46 |
+
*/
|
47 |
+
public function isDefault()
|
48 |
+
{
|
49 |
+
return $this->default;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* sets instance properties from an array of values
|
54 |
+
*
|
55 |
+
* @access protected
|
56 |
+
* @param array $paypalAccountAttribs array of paypalAccount data
|
57 |
+
* @return none
|
58 |
+
*/
|
59 |
+
protected function _initialize($paypalAccountAttribs)
|
60 |
+
{
|
61 |
+
// set the attributes
|
62 |
+
$this->_attributes = $paypalAccountAttribs;
|
63 |
+
|
64 |
+
$subscriptionArray = array();
|
65 |
+
if (isset($paypalAccountAttribs['subscriptions'])) {
|
66 |
+
foreach ($paypalAccountAttribs['subscriptions'] AS $subscription) {
|
67 |
+
$subscriptionArray[] = Braintree_Subscription::factory($subscription);
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
$this->_set('subscriptions', $subscriptionArray);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* create a printable representation of the object as:
|
76 |
+
* ClassName[property=value, property=value]
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public function __toString()
|
80 |
+
{
|
81 |
+
return __CLASS__ . '[' .
|
82 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
// static methods redirecting to gateway
|
87 |
+
|
88 |
+
public static function find($token)
|
89 |
+
{
|
90 |
+
return Braintree_Configuration::gateway()->payPalAccount()->find($token);
|
91 |
+
}
|
92 |
+
|
93 |
+
public static function update($token, $attributes)
|
94 |
+
{
|
95 |
+
return Braintree_Configuration::gateway()->payPalAccount()->update($token, $attributes);
|
96 |
+
}
|
97 |
+
|
98 |
+
public static function delete($token)
|
99 |
+
{
|
100 |
+
return Braintree_Configuration::gateway()->payPalAccount()->delete($token);
|
101 |
+
}
|
102 |
+
|
103 |
+
public static function sale($token, $transactionAttribs)
|
104 |
+
{
|
105 |
+
return Braintree_Configuration::gateway()->payPalAccount()->sale($token, $transactionAttribs);
|
106 |
+
}
|
107 |
+
}
|
lib/Braintree/PayPalAccountGateway.php
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PayPalAccountGateway module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Manages Braintree PayPalAccounts
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*/
|
20 |
+
class Braintree_PayPalAccountGateway
|
21 |
+
{
|
22 |
+
private $_gateway;
|
23 |
+
private $_config;
|
24 |
+
private $_http;
|
25 |
+
|
26 |
+
public function __construct($gateway)
|
27 |
+
{
|
28 |
+
$this->_gateway = $gateway;
|
29 |
+
$this->_config = $gateway->config;
|
30 |
+
$this->_http = new Braintree_Http($gateway->config);
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* find a paypalAccount by token
|
36 |
+
*
|
37 |
+
* @access public
|
38 |
+
* @param string $token paypal accountunique id
|
39 |
+
* @return object Braintree_PayPalAccount
|
40 |
+
* @throws Braintree_Exception_NotFound
|
41 |
+
*/
|
42 |
+
public function find($token)
|
43 |
+
{
|
44 |
+
$this->_validateId($token);
|
45 |
+
try {
|
46 |
+
$path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token;
|
47 |
+
$response = $this->_http->get($path);
|
48 |
+
return Braintree_PayPalAccount::factory($response['paypalAccount']);
|
49 |
+
} catch (Braintree_Exception_NotFound $e) {
|
50 |
+
throw new Braintree_Exception_NotFound(
|
51 |
+
'paypal account with token ' . $token . ' not found'
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* updates the paypalAccount record
|
59 |
+
*
|
60 |
+
* if calling this method in context, $token
|
61 |
+
* is the 2nd attribute. $token is not sent in object context.
|
62 |
+
*
|
63 |
+
* @access public
|
64 |
+
* @param array $attributes
|
65 |
+
* @param string $token (optional)
|
66 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
67 |
+
*/
|
68 |
+
public function update($token, $attributes)
|
69 |
+
{
|
70 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
|
71 |
+
$this->_validateId($token);
|
72 |
+
return $this->_doUpdate('put', '/payment_methods/paypal_account/' . $token, array('paypalAccount' => $attributes));
|
73 |
+
}
|
74 |
+
|
75 |
+
public function delete($token)
|
76 |
+
{
|
77 |
+
$this->_validateId($token);
|
78 |
+
$path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token;
|
79 |
+
$this->_http->delete($path);
|
80 |
+
return new Braintree_Result_Successful();
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* create a new sale for the current PayPal account
|
85 |
+
*
|
86 |
+
* @param string $token
|
87 |
+
* @param array $transactionAttribs
|
88 |
+
* @return object Braintree_Result_Successful or Braintree_Result_Error
|
89 |
+
* @see Braintree_Transaction::sale()
|
90 |
+
*/
|
91 |
+
public function sale($token, $transactionAttribs)
|
92 |
+
{
|
93 |
+
$this->_validateId($token);
|
94 |
+
return Braintree_Transaction::sale(
|
95 |
+
array_merge(
|
96 |
+
$transactionAttribs,
|
97 |
+
array('paymentMethodToken' => $token)
|
98 |
+
)
|
99 |
+
);
|
100 |
+
}
|
101 |
+
|
102 |
+
public static function updateSignature()
|
103 |
+
{
|
104 |
+
return array(
|
105 |
+
'token',
|
106 |
+
array('options' => array('makeDefault'))
|
107 |
+
);
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* sends the update request to the gateway
|
112 |
+
*
|
113 |
+
* @ignore
|
114 |
+
* @param string $subPath
|
115 |
+
* @param array $params
|
116 |
+
* @return mixed
|
117 |
+
*/
|
118 |
+
private function _doUpdate($httpVerb, $subPath, $params)
|
119 |
+
{
|
120 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
121 |
+
$response = $this->_http->$httpVerb($fullPath, $params);
|
122 |
+
return $this->_verifyGatewayResponse($response);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* generic method for validating incoming gateway responses
|
127 |
+
*
|
128 |
+
* creates a new Braintree_PayPalAccount object and encapsulates
|
129 |
+
* it inside a Braintree_Result_Successful object, or
|
130 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
131 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
132 |
+
*
|
133 |
+
* @ignore
|
134 |
+
* @param array $response gateway response values
|
135 |
+
* @return object Result_Successful or Result_Error
|
136 |
+
* @throws Braintree_Exception_Unexpected
|
137 |
+
*/
|
138 |
+
private function _verifyGatewayResponse($response)
|
139 |
+
{
|
140 |
+
if (isset($response['paypalAccount'])) {
|
141 |
+
// return a populated instance of Braintree_PayPalAccount
|
142 |
+
return new Braintree_Result_Successful(
|
143 |
+
Braintree_PayPalAccount::factory($response['paypalAccount'])
|
144 |
+
);
|
145 |
+
} else if (isset($response['apiErrorResponse'])) {
|
146 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
147 |
+
} else {
|
148 |
+
throw new Braintree_Exception_Unexpected(
|
149 |
+
'Expected paypal account or apiErrorResponse'
|
150 |
+
);
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* verifies that a valid paypal account identifier is being used
|
156 |
+
* @ignore
|
157 |
+
* @param string $identifier
|
158 |
+
* @param Optional $string $identifierType type of identifier supplied, default 'token'
|
159 |
+
* @throws InvalidArgumentException
|
160 |
+
*/
|
161 |
+
private function _validateId($identifier = null, $identifierType = 'token')
|
162 |
+
{
|
163 |
+
if (empty($identifier)) {
|
164 |
+
throw new InvalidArgumentException(
|
165 |
+
'expected paypal account id to be set'
|
166 |
+
);
|
167 |
+
}
|
168 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
|
169 |
+
throw new InvalidArgumentException(
|
170 |
+
$identifier . ' is an invalid paypal account ' . $identifierType . '.'
|
171 |
+
);
|
172 |
+
}
|
173 |
+
}
|
174 |
+
}
|
lib/Braintree/PaymentInstrumentType.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class Braintree_PaymentInstrumentType
|
4 |
+
{
|
5 |
+
const PAYPAL_ACCOUNT = 'paypal_account';
|
6 |
+
const COINBASE_ACCOUNT = 'coinbase_account';
|
7 |
+
const SEPA_BANK_ACCOUNT = 'sepa_bank_account';
|
8 |
+
const CREDIT_CARD = 'credit_card';
|
9 |
+
}
|
lib/Braintree/PaymentMethod.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PaymentMethod module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Creates and manages Braintree PaymentMethods
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
*/
|
21 |
+
class Braintree_PaymentMethod extends Braintree
|
22 |
+
{
|
23 |
+
// static methods redirecting to gateway
|
24 |
+
|
25 |
+
public static function create($attribs)
|
26 |
+
{
|
27 |
+
return Braintree_Configuration::gateway()->paymentMethod()->create($attribs);
|
28 |
+
}
|
29 |
+
|
30 |
+
public static function find($token)
|
31 |
+
{
|
32 |
+
return Braintree_Configuration::gateway()->paymentMethod()->find($token);
|
33 |
+
}
|
34 |
+
|
35 |
+
public static function update($token, $attribs)
|
36 |
+
{
|
37 |
+
return Braintree_Configuration::gateway()->paymentMethod()->update($token, $attribs);
|
38 |
+
}
|
39 |
+
|
40 |
+
public static function delete($token)
|
41 |
+
{
|
42 |
+
return Braintree_Configuration::gateway()->paymentMethod()->delete($token);
|
43 |
+
}
|
44 |
+
}
|
lib/Braintree/PaymentMethodGateway.php
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PaymentMethodGateway module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Creates and manages Braintree PaymentMethods
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
*/
|
21 |
+
class Braintree_PaymentMethodGateway
|
22 |
+
{
|
23 |
+
private $_gateway;
|
24 |
+
private $_config;
|
25 |
+
private $_http;
|
26 |
+
|
27 |
+
public function __construct($gateway)
|
28 |
+
{
|
29 |
+
$this->_gateway = $gateway;
|
30 |
+
$this->_config = $gateway->config;
|
31 |
+
$this->_http = new Braintree_Http($gateway->config);
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
public function create($attribs)
|
36 |
+
{
|
37 |
+
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
|
38 |
+
return $this->_doCreate('/payment_methods', array('payment_method' => $attribs));
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* find a PaymentMethod by token
|
43 |
+
*
|
44 |
+
* @access public
|
45 |
+
* @param string $token payment method unique id
|
46 |
+
* @return object Braintree_CreditCard or Braintree_PayPalAccount
|
47 |
+
* @throws Braintree_Exception_NotFound
|
48 |
+
*/
|
49 |
+
public function find($token)
|
50 |
+
{
|
51 |
+
$this->_validateId($token);
|
52 |
+
try {
|
53 |
+
$path = $this->_config->merchantPath() . '/payment_methods/any/' . $token;
|
54 |
+
$response = $this->_http->get($path);
|
55 |
+
if (isset($response['creditCard'])) {
|
56 |
+
return Braintree_CreditCard::factory($response['creditCard']);
|
57 |
+
} else if (isset($response['paypalAccount'])) {
|
58 |
+
return Braintree_PayPalAccount::factory($response['paypalAccount']);
|
59 |
+
} else if (isset($response['coinbaseAccount'])) {
|
60 |
+
return Braintree_CoinbaseAccount::factory($response['coinbaseAccount']);
|
61 |
+
} else if (isset($response['applePayCard'])) {
|
62 |
+
return Braintree_ApplePayCard::factory($response['applePayCard']);
|
63 |
+
} else if (is_array($response)) {
|
64 |
+
return Braintree_UnknownPaymentMethod::factory($response);
|
65 |
+
}
|
66 |
+
} catch (Braintree_Exception_NotFound $e) {
|
67 |
+
throw new Braintree_Exception_NotFound(
|
68 |
+
'payment method with token ' . $token . ' not found'
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
}
|
73 |
+
|
74 |
+
public function update($token, $attribs)
|
75 |
+
{
|
76 |
+
Braintree_Util::verifyKeys(self::updateSignature(), $attribs);
|
77 |
+
return $this->_doUpdate('/payment_methods/any/' . $token, array('payment_method' => $attribs));
|
78 |
+
}
|
79 |
+
|
80 |
+
public function delete($token)
|
81 |
+
{
|
82 |
+
$this->_validateId($token);
|
83 |
+
$path = $this->_config->merchantPath() . '/payment_methods/any/' . $token;
|
84 |
+
$this->_http->delete($path);
|
85 |
+
return new Braintree_Result_Successful();
|
86 |
+
}
|
87 |
+
|
88 |
+
private static function baseSignature($options)
|
89 |
+
{
|
90 |
+
$billingAddressSignature = Braintree_AddressGateway::createSignature();
|
91 |
+
return array(
|
92 |
+
'customerId',
|
93 |
+
'paymentMethodNonce',
|
94 |
+
'token',
|
95 |
+
'billingAddressId',
|
96 |
+
'deviceData',
|
97 |
+
array('options' => $options),
|
98 |
+
array('billingAddress' => $billingAddressSignature)
|
99 |
+
);
|
100 |
+
}
|
101 |
+
|
102 |
+
public static function createSignature()
|
103 |
+
{
|
104 |
+
$options = array(
|
105 |
+
'makeDefault',
|
106 |
+
'verifyCard',
|
107 |
+
'failOnDuplicatePaymentMethod',
|
108 |
+
'verificationMerchantAccountId'
|
109 |
+
);
|
110 |
+
$signature = self::baseSignature($options);
|
111 |
+
return $signature;
|
112 |
+
}
|
113 |
+
|
114 |
+
public static function updateSignature()
|
115 |
+
{
|
116 |
+
$billingAddressSignature = Braintree_AddressGateway::updateSignature();
|
117 |
+
array_push($billingAddressSignature, array(
|
118 |
+
'options' => array(
|
119 |
+
'updateExisting'
|
120 |
+
)
|
121 |
+
));
|
122 |
+
return array(
|
123 |
+
'billingAddressId',
|
124 |
+
'cardholderName',
|
125 |
+
'cvv',
|
126 |
+
'deviceSessionId',
|
127 |
+
'expirationDate',
|
128 |
+
'expirationMonth',
|
129 |
+
'expirationYear',
|
130 |
+
'number',
|
131 |
+
'token',
|
132 |
+
'venmoSdkPaymentMethodCode',
|
133 |
+
'deviceData',
|
134 |
+
'fraudMerchantId',
|
135 |
+
'paymentMethodNonce',
|
136 |
+
array('options' => array(
|
137 |
+
'makeDefault',
|
138 |
+
'verificationMerchantAccountId',
|
139 |
+
'verifyCard',
|
140 |
+
'venmoSdkSession'
|
141 |
+
)),
|
142 |
+
array('billingAddress' => $billingAddressSignature)
|
143 |
+
);
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* sends the create request to the gateway
|
148 |
+
*
|
149 |
+
* @ignore
|
150 |
+
* @param string $subPath
|
151 |
+
* @param array $params
|
152 |
+
* @return mixed
|
153 |
+
*/
|
154 |
+
public function _doCreate($subPath, $params)
|
155 |
+
{
|
156 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
157 |
+
$response = $this->_http->post($fullPath, $params);
|
158 |
+
|
159 |
+
return $this->_verifyGatewayResponse($response);
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* sends the update request to the gateway
|
164 |
+
*
|
165 |
+
* @ignore
|
166 |
+
* @param string $subPath
|
167 |
+
* @param array $params
|
168 |
+
* @return mixed
|
169 |
+
*/
|
170 |
+
public function _doUpdate($subPath, $params)
|
171 |
+
{
|
172 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
173 |
+
$response = $this->_http->put($fullPath, $params);
|
174 |
+
|
175 |
+
return $this->_verifyGatewayResponse($response);
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* generic method for validating incoming gateway responses
|
180 |
+
*
|
181 |
+
* creates a new Braintree_CreditCard or Braintree_PayPalAccount object
|
182 |
+
* and encapsulates it inside a Braintree_Result_Successful object, or
|
183 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
184 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
185 |
+
*
|
186 |
+
* @ignore
|
187 |
+
* @param array $response gateway response values
|
188 |
+
* @return object Result_Successful or Result_Error
|
189 |
+
* @throws Braintree_Exception_Unexpected
|
190 |
+
*/
|
191 |
+
private function _verifyGatewayResponse($response)
|
192 |
+
{
|
193 |
+
if (isset($response['creditCard'])) {
|
194 |
+
// return a populated instance of Braintree_CreditCard
|
195 |
+
return new Braintree_Result_Successful(
|
196 |
+
Braintree_CreditCard::factory($response['creditCard']),
|
197 |
+
"paymentMethod"
|
198 |
+
);
|
199 |
+
} else if (isset($response['paypalAccount'])) {
|
200 |
+
// return a populated instance of Braintree_PayPalAccount
|
201 |
+
return new Braintree_Result_Successful(
|
202 |
+
Braintree_PayPalAccount::factory($response['paypalAccount']),
|
203 |
+
"paymentMethod"
|
204 |
+
);
|
205 |
+
} else if (isset($response['coinbaseAccount'])) {
|
206 |
+
// return a populated instance of Braintree_CoinbaseAccount
|
207 |
+
return new Braintree_Result_Successful(
|
208 |
+
Braintree_CoinbaseAccount::factory($response['coinbaseAccount']),
|
209 |
+
"paymentMethod"
|
210 |
+
);
|
211 |
+
} else if (isset($response['applePayCard'])) {
|
212 |
+
// return a populated instance of Braintree_ApplePayCard
|
213 |
+
return new Braintree_Result_Successful(
|
214 |
+
Braintree_ApplePayCard::factory($response['applePayCard']),
|
215 |
+
"paymentMethod"
|
216 |
+
);
|
217 |
+
} else if (isset($response['apiErrorResponse'])) {
|
218 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
219 |
+
} else if (is_array($response)) {
|
220 |
+
return new Braintree_Result_Successful(
|
221 |
+
Braintree_UnknownPaymentMethod::factory($response),
|
222 |
+
"paymentMethod"
|
223 |
+
);
|
224 |
+
} else {
|
225 |
+
throw new Braintree_Exception_Unexpected(
|
226 |
+
'Expected payment method or apiErrorResponse'
|
227 |
+
);
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* verifies that a valid payment method identifier is being used
|
233 |
+
* @ignore
|
234 |
+
* @param string $identifier
|
235 |
+
* @param Optional $string $identifierType type of identifier supplied, default 'token'
|
236 |
+
* @throws InvalidArgumentException
|
237 |
+
*/
|
238 |
+
private function _validateId($identifier = null, $identifierType = 'token')
|
239 |
+
{
|
240 |
+
if (empty($identifier)) {
|
241 |
+
throw new InvalidArgumentException(
|
242 |
+
'expected payment method id to be set'
|
243 |
+
);
|
244 |
+
}
|
245 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
|
246 |
+
throw new InvalidArgumentException(
|
247 |
+
$identifier . ' is an invalid payment method ' . $identifierType . '.'
|
248 |
+
);
|
249 |
+
}
|
250 |
+
}
|
251 |
+
}
|
lib/Braintree/PaymentMethodNonce.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PaymentMethodNonce module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Creates and manages Braintree PaymentMethodNonces
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
*/
|
21 |
+
class Braintree_PaymentMethodNonce extends Braintree
|
22 |
+
{
|
23 |
+
// static methods redirecting to gateway
|
24 |
+
|
25 |
+
public static function create($token)
|
26 |
+
{
|
27 |
+
return Braintree_Configuration::gateway()->paymentMethodNonce()->create($token);
|
28 |
+
}
|
29 |
+
|
30 |
+
public static function factory($attributes)
|
31 |
+
{
|
32 |
+
$defaultAttributes = array(
|
33 |
+
'nonce' => '',
|
34 |
+
);
|
35 |
+
|
36 |
+
$instance = new self();
|
37 |
+
$instance->_initialize(array_merge($defaultAttributes, $attributes));
|
38 |
+
return $instance;
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function _initialize($nonceAttributes)
|
42 |
+
{
|
43 |
+
$this->_attributes = $nonceAttributes;
|
44 |
+
$this->_set('nonce', $nonceAttributes['nonce']);
|
45 |
+
}
|
46 |
+
}
|
lib/Braintree/PaymentMethodNonceGateway.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree PaymentMethodNonceGateway module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Creates and manages Braintree PaymentMethodNonces
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
*/
|
21 |
+
class Braintree_PaymentMethodNonceGateway
|
22 |
+
{
|
23 |
+
private $_gateway;
|
24 |
+
private $_config;
|
25 |
+
private $_http;
|
26 |
+
|
27 |
+
public function __construct($gateway)
|
28 |
+
{
|
29 |
+
$this->_gateway = $gateway;
|
30 |
+
$this->_config = $gateway->config;
|
31 |
+
$this->_http = new Braintree_Http($gateway->config);
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
public function create($token)
|
36 |
+
{
|
37 |
+
$subPath = '/payment_methods/' . $token . '/nonces';
|
38 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
39 |
+
$response = $this->_http->post($fullPath);
|
40 |
+
|
41 |
+
return new Braintree_Result_Successful(
|
42 |
+
Braintree_PaymentMethodNonce::factory($response['paymentMethodNonce']),
|
43 |
+
"paymentMethodNonce"
|
44 |
+
);
|
45 |
+
}
|
46 |
+
}
|
lib/Braintree/Plan.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_Plan extends Braintree
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self();
|
7 |
+
$instance->_initialize($attributes);
|
8 |
+
|
9 |
+
return $instance;
|
10 |
+
}
|
11 |
+
|
12 |
+
protected function _initialize($attributes)
|
13 |
+
{
|
14 |
+
$this->_attributes = $attributes;
|
15 |
+
|
16 |
+
$addOnArray = array();
|
17 |
+
if (isset($attributes['addOns'])) {
|
18 |
+
foreach ($attributes['addOns'] AS $addOn) {
|
19 |
+
$addOnArray[] = Braintree_AddOn::factory($addOn);
|
20 |
+
}
|
21 |
+
}
|
22 |
+
$this->_attributes['addOns'] = $addOnArray;
|
23 |
+
|
24 |
+
$discountArray = array();
|
25 |
+
if (isset($attributes['discounts'])) {
|
26 |
+
foreach ($attributes['discounts'] AS $discount) {
|
27 |
+
$discountArray[] = Braintree_Discount::factory($discount);
|
28 |
+
}
|
29 |
+
}
|
30 |
+
$this->_attributes['discounts'] = $discountArray;
|
31 |
+
|
32 |
+
$planArray = array();
|
33 |
+
if (isset($attributes['plans'])) {
|
34 |
+
foreach ($attributes['plans'] AS $plan) {
|
35 |
+
$planArray[] = Braintree_Plan::factory($plan);
|
36 |
+
}
|
37 |
+
}
|
38 |
+
$this->_attributes['plans'] = $planArray;
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
// static methods redirecting to gateway
|
43 |
+
|
44 |
+
public static function all()
|
45 |
+
{
|
46 |
+
return Braintree_Configuration::gateway()->plan()->all();
|
47 |
+
}
|
48 |
+
}
|
lib/Braintree/PlanGateway.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_PlanGateway
|
3 |
+
{
|
4 |
+
private $_gateway;
|
5 |
+
private $_config;
|
6 |
+
private $_http;
|
7 |
+
|
8 |
+
public function __construct($gateway)
|
9 |
+
{
|
10 |
+
$this->_gateway = $gateway;
|
11 |
+
$this->_config = $gateway->config;
|
12 |
+
$this->_http = new Braintree_Http($gateway->config);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function all()
|
16 |
+
{
|
17 |
+
$path = $this->_config->merchantPath() . '/plans';
|
18 |
+
$response = $this->_http->get($path);
|
19 |
+
if (key_exists('plans', $response)){
|
20 |
+
$plans = array("plan" => $response['plans']);
|
21 |
+
} else {
|
22 |
+
$plans = array("plan" => array());
|
23 |
+
}
|
24 |
+
|
25 |
+
return Braintree_Util::extractAttributeAsArray(
|
26 |
+
$plans,
|
27 |
+
'plan'
|
28 |
+
);
|
29 |
+
}
|
30 |
+
}
|
lib/Braintree/RangeNode.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_RangeNode
|
4 |
+
{
|
5 |
+
function __construct($name)
|
6 |
+
{
|
7 |
+
$this->name = $name;
|
8 |
+
$this->searchTerms = array();
|
9 |
+
}
|
10 |
+
|
11 |
+
function greaterThanOrEqualTo($value)
|
12 |
+
{
|
13 |
+
$this->searchTerms['min'] = $value;
|
14 |
+
return $this;
|
15 |
+
}
|
16 |
+
|
17 |
+
function lessThanOrEqualTo($value)
|
18 |
+
{
|
19 |
+
$this->searchTerms['max'] = $value;
|
20 |
+
return $this;
|
21 |
+
}
|
22 |
+
|
23 |
+
function is($value)
|
24 |
+
{
|
25 |
+
$this->searchTerms['is'] = $value;
|
26 |
+
return $this;
|
27 |
+
}
|
28 |
+
|
29 |
+
function between($min, $max)
|
30 |
+
{
|
31 |
+
return $this->greaterThanOrEqualTo($min)->lessThanOrEqualTo($max);
|
32 |
+
}
|
33 |
+
|
34 |
+
function toParam()
|
35 |
+
{
|
36 |
+
return $this->searchTerms;
|
37 |
+
}
|
38 |
+
}
|
lib/Braintree/ResourceCollection.php
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree ResourceCollection
|
4 |
+
* ResourceCollection is a container object for result data
|
5 |
+
*
|
6 |
+
* stores and retrieves search results and aggregate data
|
7 |
+
*
|
8 |
+
* example:
|
9 |
+
* <code>
|
10 |
+
* $result = Braintree_Customer::all();
|
11 |
+
*
|
12 |
+
* foreach($result as $transaction) {
|
13 |
+
* print_r($transaction->id);
|
14 |
+
* }
|
15 |
+
* </code>
|
16 |
+
*
|
17 |
+
* @package Braintree
|
18 |
+
* @subpackage Utility
|
19 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
20 |
+
*/
|
21 |
+
class Braintree_ResourceCollection implements Iterator
|
22 |
+
{
|
23 |
+
private $_index;
|
24 |
+
private $_batchIndex;
|
25 |
+
private $_items;
|
26 |
+
private $_pageSize;
|
27 |
+
private $_pager;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* set up the resource collection
|
31 |
+
*
|
32 |
+
* expects an array of attributes with literal keys
|
33 |
+
*
|
34 |
+
* @param array $attributes
|
35 |
+
* @param array $pagerAttribs
|
36 |
+
*/
|
37 |
+
public function __construct($response, $pager)
|
38 |
+
{
|
39 |
+
$this->_pageSize = $response["searchResults"]["pageSize"];
|
40 |
+
$this->_ids = $response["searchResults"]["ids"];
|
41 |
+
$this->_pager = $pager;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* returns the current item when iterating with foreach
|
46 |
+
*/
|
47 |
+
public function current()
|
48 |
+
{
|
49 |
+
return $this->_items[$this->_index];
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* returns the first item in the collection
|
54 |
+
*
|
55 |
+
* @return mixed
|
56 |
+
*/
|
57 |
+
public function firstItem()
|
58 |
+
{
|
59 |
+
$ids = $this->_ids;
|
60 |
+
$page = $this->_getPage(array($ids[0]));
|
61 |
+
return $page[0];
|
62 |
+
}
|
63 |
+
|
64 |
+
public function key()
|
65 |
+
{
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* advances to the next item in the collection when iterating with foreach
|
71 |
+
*/
|
72 |
+
public function next()
|
73 |
+
{
|
74 |
+
++$this->_index;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* rewinds the testIterateOverResults collection to the first item when iterating with foreach
|
79 |
+
*/
|
80 |
+
public function rewind()
|
81 |
+
{
|
82 |
+
$this->_batchIndex = 0;
|
83 |
+
$this->_getNextPage();
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* returns whether the current item is valid when iterating with foreach
|
88 |
+
*/
|
89 |
+
public function valid()
|
90 |
+
{
|
91 |
+
if ($this->_index == count($this->_items) && $this->_batchIndex < count($this->_ids)) {
|
92 |
+
$this->_getNextPage();
|
93 |
+
}
|
94 |
+
|
95 |
+
if ($this->_index < count($this->_items)) {
|
96 |
+
return true;
|
97 |
+
} else {
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
public function maximumCount()
|
103 |
+
{
|
104 |
+
return count($this->_ids);
|
105 |
+
}
|
106 |
+
|
107 |
+
private function _getNextPage()
|
108 |
+
{
|
109 |
+
if (empty($this->_ids))
|
110 |
+
{
|
111 |
+
$this->_items = array();
|
112 |
+
}
|
113 |
+
else
|
114 |
+
{
|
115 |
+
$this->_items = $this->_getPage(array_slice($this->_ids, $this->_batchIndex, $this->_pageSize));
|
116 |
+
$this->_batchIndex += $this->_pageSize;
|
117 |
+
$this->_index = 0;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* requests the next page of results for the collection
|
123 |
+
*
|
124 |
+
* @return none
|
125 |
+
*/
|
126 |
+
private function _getPage($ids)
|
127 |
+
{
|
128 |
+
$object = $this->_pager['object'];
|
129 |
+
$method = $this->_pager['method'];
|
130 |
+
$methodArgs = array();
|
131 |
+
foreach ($this->_pager['methodArgs'] as $arg) {
|
132 |
+
array_push($methodArgs, $arg);
|
133 |
+
}
|
134 |
+
array_push($methodArgs, $ids);
|
135 |
+
|
136 |
+
return call_user_func_array(
|
137 |
+
array($object, $method),
|
138 |
+
$methodArgs
|
139 |
+
);
|
140 |
+
}
|
141 |
+
}
|
lib/Braintree/Result/CreditCardVerification.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Credit Card Verification Result
|
4 |
+
*
|
5 |
+
* This object is returned as part of an Error Result; it provides
|
6 |
+
* access to the credit card verification data from the gateway
|
7 |
+
*
|
8 |
+
*
|
9 |
+
* @package Braintree
|
10 |
+
* @subpackage Result
|
11 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
12 |
+
*
|
13 |
+
* @property-read string $avsErrorResponseCode
|
14 |
+
* @property-read string $avsPostalCodeResponseCode
|
15 |
+
* @property-read string $avsStreetAddressResponseCode
|
16 |
+
* @property-read string $cvvResponseCode
|
17 |
+
* @property-read string $status
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
class Braintree_Result_CreditCardVerification
|
21 |
+
{
|
22 |
+
// Status
|
23 |
+
const FAILED = 'failed';
|
24 |
+
const GATEWAY_REJECTED = 'gateway_rejected';
|
25 |
+
const PROCESSOR_DECLINED = 'processor_declined';
|
26 |
+
const VERIFIED = 'verified';
|
27 |
+
|
28 |
+
private $_attributes;
|
29 |
+
private $_avsErrorResponseCode;
|
30 |
+
private $_avsPostalCodeResponseCode;
|
31 |
+
private $_avsStreetAddressResponseCode;
|
32 |
+
private $_cvvResponseCode;
|
33 |
+
private $_gatewayRejectionReason;
|
34 |
+
private $_status;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @ignore
|
38 |
+
*/
|
39 |
+
public function __construct($attributes)
|
40 |
+
{
|
41 |
+
$this->_initializeFromArray($attributes);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* initializes instance properties from the keys/values of an array
|
46 |
+
* @ignore
|
47 |
+
* @access protected
|
48 |
+
* @param <type> $aAttribs array of properties to set - single level
|
49 |
+
* @return none
|
50 |
+
*/
|
51 |
+
private function _initializeFromArray($attributes)
|
52 |
+
{
|
53 |
+
if(isset($attributes['riskData']))
|
54 |
+
{
|
55 |
+
$attributes['riskData'] = Braintree_RiskData::factory($attributes['riskData']);
|
56 |
+
}
|
57 |
+
|
58 |
+
$this->_attributes = $attributes;
|
59 |
+
foreach($attributes AS $name => $value) {
|
60 |
+
$varName = "_$name";
|
61 |
+
$this->$varName = $value;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
*
|
67 |
+
* @ignore
|
68 |
+
*/
|
69 |
+
public function __get($name)
|
70 |
+
{
|
71 |
+
$varName = "_$name";
|
72 |
+
return isset($this->$varName) ? $this->$varName : null;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* returns a string representation of the customer
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public function __toString()
|
80 |
+
{
|
81 |
+
return __CLASS__ . '[' .
|
82 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
83 |
+
}
|
84 |
+
}
|
lib/Braintree/Result/Error.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Error Result
|
4 |
+
*
|
5 |
+
* An Error Result will be returned from gateway methods when
|
6 |
+
* the gateway responds with an error. It will provide access
|
7 |
+
* to the original request.
|
8 |
+
* For example, when voiding a transaction, Error Result will
|
9 |
+
* respond to the void request if it failed:
|
10 |
+
*
|
11 |
+
* <code>
|
12 |
+
* $result = Braintree_Transaction::void('abc123');
|
13 |
+
* if ($result->success) {
|
14 |
+
* // Successful Result
|
15 |
+
* } else {
|
16 |
+
* // Braintree_Result_Error
|
17 |
+
* }
|
18 |
+
* </code>
|
19 |
+
*
|
20 |
+
* @package Braintree
|
21 |
+
* @subpackage Result
|
22 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
23 |
+
*
|
24 |
+
* @property-read array $params original passed params
|
25 |
+
* @property-read object $errors Braintree_Error_ErrorCollection
|
26 |
+
* @property-read object $creditCardVerification credit card verification data
|
27 |
+
*/
|
28 |
+
class Braintree_Result_Error extends Braintree
|
29 |
+
{
|
30 |
+
/**
|
31 |
+
*
|
32 |
+
* @var boolean always false
|
33 |
+
*/
|
34 |
+
public $success = false;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* return original value for a field
|
38 |
+
* For example, if a user tried to submit 'invalid-email' in the html field transaction[customer][email],
|
39 |
+
* $result->valueForHtmlField("transaction[customer][email]") would yield "invalid-email"
|
40 |
+
*
|
41 |
+
* @param string $field
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function valueForHtmlField($field)
|
45 |
+
{
|
46 |
+
$pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY);
|
47 |
+
$params = $this->params;
|
48 |
+
foreach(array_slice($pieces, 0, -1) as $key) {
|
49 |
+
$params = $params[Braintree_Util::delimiterToCamelCase($key)];
|
50 |
+
}
|
51 |
+
if ($key != 'custom_fields') {
|
52 |
+
$finalKey = Braintree_Util::delimiterToCamelCase(end($pieces));
|
53 |
+
} else {
|
54 |
+
$finalKey = end($pieces);
|
55 |
+
}
|
56 |
+
$fieldValue = isset($params[$finalKey]) ? $params[$finalKey] : null;
|
57 |
+
return $fieldValue;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* overrides default constructor
|
62 |
+
* @ignore
|
63 |
+
* @param array $response gateway response array
|
64 |
+
*/
|
65 |
+
public function __construct($response)
|
66 |
+
{
|
67 |
+
$this->_attributes = $response;
|
68 |
+
$this->_set('errors', new Braintree_Error_ErrorCollection($response['errors']));
|
69 |
+
|
70 |
+
if(isset($response['verification'])) {
|
71 |
+
$this->_set('creditCardVerification', new Braintree_Result_CreditCardVerification($response['verification']));
|
72 |
+
} else {
|
73 |
+
$this->_set('creditCardVerification', null);
|
74 |
+
}
|
75 |
+
|
76 |
+
if(isset($response['transaction'])) {
|
77 |
+
$this->_set('transaction', Braintree_Transaction::factory($response['transaction']));
|
78 |
+
} else {
|
79 |
+
$this->_set('transaction', null);
|
80 |
+
}
|
81 |
+
|
82 |
+
if(isset($response['subscription'])) {
|
83 |
+
$this->_set('subscription', Braintree_Subscription::factory($response['subscription']));
|
84 |
+
} else {
|
85 |
+
$this->_set('subscription', null);
|
86 |
+
}
|
87 |
+
|
88 |
+
if(isset($response['merchantAccount'])) {
|
89 |
+
$this->_set('merchantAccount', Braintree_MerchantAccount::factory($response['merchantAccount']));
|
90 |
+
} else {
|
91 |
+
$this->_set('merchantAccount', null);
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* create a printable representation of the object as:
|
97 |
+
* ClassName[property=value, property=value]
|
98 |
+
* @ignore
|
99 |
+
* @return var
|
100 |
+
*/
|
101 |
+
public function __toString()
|
102 |
+
{
|
103 |
+
$output = Braintree_Util::attributesToString($this->_attributes);
|
104 |
+
if (isset($this->_creditCardVerification)) {
|
105 |
+
$output .= sprintf('%s', $this->_creditCardVerification);
|
106 |
+
}
|
107 |
+
return __CLASS__ .'['.$output.']';
|
108 |
+
}
|
109 |
+
}
|
lib/Braintree/Result/Successful.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Successful Result
|
4 |
+
*
|
5 |
+
* A Successful Result will be returned from gateway methods when
|
6 |
+
* validations pass. It will provide access to the created resource.
|
7 |
+
*
|
8 |
+
* For example, when creating a customer, Braintree_Result_Successful will
|
9 |
+
* respond to <b>customer</b> like so:
|
10 |
+
*
|
11 |
+
* <code>
|
12 |
+
* $result = Braintree_Customer::create(array('first_name' => "John"));
|
13 |
+
* if ($result->success) {
|
14 |
+
* // Braintree_Result_Successful
|
15 |
+
* echo "Created customer {$result->customer->id}";
|
16 |
+
* } else {
|
17 |
+
* // Braintree_Result_Error
|
18 |
+
* }
|
19 |
+
* </code>
|
20 |
+
*
|
21 |
+
*
|
22 |
+
* @package Braintree
|
23 |
+
* @subpackage Result
|
24 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
25 |
+
*/
|
26 |
+
class Braintree_Result_Successful extends Braintree_Instance
|
27 |
+
{
|
28 |
+
/**
|
29 |
+
*
|
30 |
+
* @var boolean always true
|
31 |
+
*/
|
32 |
+
public $success = true;
|
33 |
+
/**
|
34 |
+
*
|
35 |
+
* @var string stores the internal name of the object providing access to
|
36 |
+
*/
|
37 |
+
private $_returnObjectName;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @ignore
|
41 |
+
* @param string $classToReturn name of class to instantiate
|
42 |
+
*/
|
43 |
+
public function __construct($objToReturn = null, $propertyName = null)
|
44 |
+
{
|
45 |
+
$this->_attributes = array();
|
46 |
+
|
47 |
+
if(!empty($objToReturn)) {
|
48 |
+
|
49 |
+
if(empty($propertyName)) {
|
50 |
+
$propertyName = Braintree_Util::cleanClassName(
|
51 |
+
get_class($objToReturn)
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
// save the name for indirect access
|
56 |
+
$this->_returnObjectName = $propertyName;
|
57 |
+
|
58 |
+
// create the property!
|
59 |
+
$this->$propertyName = $objToReturn;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
*
|
65 |
+
* @ignore
|
66 |
+
* @return string string representation of the object's structure
|
67 |
+
*/
|
68 |
+
public function __toString()
|
69 |
+
{
|
70 |
+
$returnObject = $this->_returnObjectName;
|
71 |
+
return __CLASS__ . '['.$this->$returnObject->__toString().']';
|
72 |
+
}
|
73 |
+
|
74 |
+
}
|
lib/Braintree/RiskData.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_RiskData extends Braintree
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self();
|
7 |
+
$instance->_initialize($attributes);
|
8 |
+
|
9 |
+
return $instance;
|
10 |
+
}
|
11 |
+
|
12 |
+
protected function _initialize($attributes)
|
13 |
+
{
|
14 |
+
$this->_attributes = $attributes;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* returns a string representation of the risk data
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
public function __toString()
|
22 |
+
{
|
23 |
+
return __CLASS__ . '[' .
|
24 |
+
Braintree_Util::attributesToString($this->_attributes) .']';
|
25 |
+
}
|
26 |
+
|
27 |
+
}
|
lib/Braintree/SettlementBatchSummary.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_SettlementBatchSummary extends Braintree
|
3 |
+
{
|
4 |
+
public static function factory($attributes)
|
5 |
+
{
|
6 |
+
$instance = new self();
|
7 |
+
$instance->_initialize($attributes);
|
8 |
+
return $instance;
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @ignore
|
13 |
+
*/
|
14 |
+
protected function _initialize($attributes)
|
15 |
+
{
|
16 |
+
$this->_attributes = $attributes;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function records()
|
20 |
+
{
|
21 |
+
return $this->_attributes['records'];
|
22 |
+
}
|
23 |
+
|
24 |
+
|
25 |
+
// static methods redirecting to gateway
|
26 |
+
|
27 |
+
public static function generate($settlement_date, $groupByCustomField = NULL)
|
28 |
+
{
|
29 |
+
return Braintree_Configuration::gateway()->settlementBatchSummary()->generate($settlement_date, $groupByCustomField);
|
30 |
+
}
|
31 |
+
}
|
lib/Braintree/SettlementBatchSummaryGateway.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_SettlementBatchSummaryGateway
|
3 |
+
{
|
4 |
+
private $_gateway;
|
5 |
+
private $_config;
|
6 |
+
private $_http;
|
7 |
+
|
8 |
+
public function __construct($gateway)
|
9 |
+
{
|
10 |
+
$this->_gateway = $gateway;
|
11 |
+
$this->_config = $gateway->config;
|
12 |
+
$this->_http = new Braintree_Http($gateway->config);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function generate($settlement_date, $groupByCustomField = NULL)
|
16 |
+
{
|
17 |
+
$criteria = array('settlement_date' => $settlement_date);
|
18 |
+
if (isset($groupByCustomField))
|
19 |
+
{
|
20 |
+
$criteria['group_by_custom_field'] = $groupByCustomField;
|
21 |
+
}
|
22 |
+
$params = array('settlement_batch_summary' => $criteria);
|
23 |
+
$path = $this->_config->merchantPath() . '/settlement_batch_summary';
|
24 |
+
$response = $this->_http->post($path, $params);
|
25 |
+
|
26 |
+
if (isset($groupByCustomField))
|
27 |
+
{
|
28 |
+
$response['settlementBatchSummary']['records'] = $this->_underscoreCustomField(
|
29 |
+
$groupByCustomField,
|
30 |
+
$response['settlementBatchSummary']['records']
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
return $this->_verifyGatewayResponse($response);
|
35 |
+
}
|
36 |
+
|
37 |
+
private function _underscoreCustomField($groupByCustomField, $records)
|
38 |
+
{
|
39 |
+
$updatedRecords = array();
|
40 |
+
|
41 |
+
foreach ($records as $record)
|
42 |
+
{
|
43 |
+
$camelized = Braintree_Util::delimiterToCamelCase($groupByCustomField);
|
44 |
+
$record[$groupByCustomField] = $record[$camelized];
|
45 |
+
unset($record[$camelized]);
|
46 |
+
$updatedRecords[] = $record;
|
47 |
+
}
|
48 |
+
|
49 |
+
return $updatedRecords;
|
50 |
+
}
|
51 |
+
|
52 |
+
private function _verifyGatewayResponse($response)
|
53 |
+
{
|
54 |
+
if (isset($response['settlementBatchSummary'])) {
|
55 |
+
return new Braintree_Result_Successful(
|
56 |
+
Braintree_SettlementBatchSummary::factory($response['settlementBatchSummary'])
|
57 |
+
);
|
58 |
+
} else if (isset($response['apiErrorResponse'])) {
|
59 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
60 |
+
} else {
|
61 |
+
throw new Braintree_Exception_Unexpected(
|
62 |
+
"Expected settlementBatchSummary or apiErrorResponse"
|
63 |
+
);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
lib/Braintree/SignatureService.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_SignatureService
|
4 |
+
{
|
5 |
+
|
6 |
+
public function __construct($key, $digest)
|
7 |
+
{
|
8 |
+
$this->key = $key;
|
9 |
+
$this->digest = $digest;
|
10 |
+
}
|
11 |
+
|
12 |
+
public function sign($payload)
|
13 |
+
{
|
14 |
+
return $this->hash($payload) . "|" . $payload;
|
15 |
+
}
|
16 |
+
|
17 |
+
public function hash($data)
|
18 |
+
{
|
19 |
+
return call_user_func($this->digest, $this->key, $data);
|
20 |
+
}
|
21 |
+
|
22 |
+
}
|
lib/Braintree/Subscription.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Subscription module
|
4 |
+
*
|
5 |
+
* <b>== More information ==</b>
|
6 |
+
*
|
7 |
+
* For more detailed information on Subscriptions, see {@link http://www.braintreepayments.com/gateway/subscription-api http://www.braintreepaymentsolutions.com/gateway/subscription-api}
|
8 |
+
*
|
9 |
+
* PHP Version 5
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_Subscription extends Braintree
|
15 |
+
{
|
16 |
+
const ACTIVE = 'Active';
|
17 |
+
const CANCELED = 'Canceled';
|
18 |
+
const EXPIRED = 'Expired';
|
19 |
+
const PAST_DUE = 'Past Due';
|
20 |
+
const PENDING = 'Pending';
|
21 |
+
|
22 |
+
// Subscription Sources
|
23 |
+
const API = 'api';
|
24 |
+
const CONTROL_PANEL = 'control_panel';
|
25 |
+
const RECURRING = 'recurring';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @ignore
|
29 |
+
*/
|
30 |
+
public static function factory($attributes)
|
31 |
+
{
|
32 |
+
$instance = new self();
|
33 |
+
$instance->_initialize($attributes);
|
34 |
+
|
35 |
+
return $instance;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @ignore
|
40 |
+
*/
|
41 |
+
protected function _initialize($attributes)
|
42 |
+
{
|
43 |
+
$this->_attributes = $attributes;
|
44 |
+
|
45 |
+
$addOnArray = array();
|
46 |
+
if (isset($attributes['addOns'])) {
|
47 |
+
foreach ($attributes['addOns'] AS $addOn) {
|
48 |
+
$addOnArray[] = Braintree_AddOn::factory($addOn);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
$this->_attributes['addOns'] = $addOnArray;
|
52 |
+
|
53 |
+
$discountArray = array();
|
54 |
+
if (isset($attributes['discounts'])) {
|
55 |
+
foreach ($attributes['discounts'] AS $discount) {
|
56 |
+
$discountArray[] = Braintree_Discount::factory($discount);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
$this->_attributes['discounts'] = $discountArray;
|
60 |
+
|
61 |
+
if (isset($attributes['descriptor'])) {
|
62 |
+
$this->_set('descriptor', new Braintree_Descriptor($attributes['descriptor']));
|
63 |
+
}
|
64 |
+
|
65 |
+
$statusHistory = array();
|
66 |
+
if (isset($attributes['statusHistory'])) {
|
67 |
+
foreach ($attributes['statusHistory'] AS $history) {
|
68 |
+
$statusHistory[] = new Braintree_Subscription_StatusDetails($history);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
$this->_attributes['statusHistory'] = $statusHistory;
|
72 |
+
|
73 |
+
$transactionArray = array();
|
74 |
+
if (isset($attributes['transactions'])) {
|
75 |
+
foreach ($attributes['transactions'] AS $transaction) {
|
76 |
+
$transactionArray[] = Braintree_Transaction::factory($transaction);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
$this->_attributes['transactions'] = $transactionArray;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* returns a string representation of the customer
|
84 |
+
* @return string
|
85 |
+
*/
|
86 |
+
public function __toString()
|
87 |
+
{
|
88 |
+
$excludedAttributes = array('statusHistory');
|
89 |
+
|
90 |
+
$displayAttributes = array();
|
91 |
+
foreach($this->_attributes as $key => $val) {
|
92 |
+
if (!in_array($key, $excludedAttributes)) {
|
93 |
+
$displayAttributes[$key] = $val;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
return __CLASS__ . '[' .
|
98 |
+
Braintree_Util::attributesToString($displayAttributes) .']';
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
// static methods redirecting to gateway
|
103 |
+
|
104 |
+
public static function create($attributes)
|
105 |
+
{
|
106 |
+
return Braintree_Configuration::gateway()->subscription()->create($attributes);
|
107 |
+
}
|
108 |
+
|
109 |
+
public static function find($id)
|
110 |
+
{
|
111 |
+
return Braintree_Configuration::gateway()->subscription()->find($id);
|
112 |
+
}
|
113 |
+
|
114 |
+
public static function search($query)
|
115 |
+
{
|
116 |
+
return Braintree_Configuration::gateway()->subscription()->search($query);
|
117 |
+
}
|
118 |
+
|
119 |
+
public static function fetch($query, $ids)
|
120 |
+
{
|
121 |
+
return Braintree_Configuration::gateway()->subscription()->fetch($query, $ids);
|
122 |
+
}
|
123 |
+
|
124 |
+
public static function update($subscriptionId, $attributes)
|
125 |
+
{
|
126 |
+
return Braintree_Configuration::gateway()->subscription()->update($subscriptionId, $attributes);
|
127 |
+
}
|
128 |
+
|
129 |
+
public static function retryCharge($subscriptionId, $amount = null)
|
130 |
+
{
|
131 |
+
return Braintree_Configuration::gateway()->subscription()->retryCharge($subscriptionId, $amount);
|
132 |
+
}
|
133 |
+
|
134 |
+
public static function cancel($subscriptionId)
|
135 |
+
{
|
136 |
+
return Braintree_Configuration::gateway()->subscription()->cancel($subscriptionId);
|
137 |
+
}
|
138 |
+
}
|
lib/Braintree/Subscription/StatusDetails.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Status details from a subscription
|
4 |
+
* Creates an instance of StatusDetails, as part of a subscription response
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*
|
9 |
+
* @property-read string $price
|
10 |
+
* @property-read string $balance
|
11 |
+
* @property-read string $status
|
12 |
+
* @property-read string $timestamp
|
13 |
+
* @property-read string $subscriptionSource
|
14 |
+
* @property-read string $user
|
15 |
+
* @uses Braintree_Instance inherits methods
|
16 |
+
*/
|
17 |
+
class Braintree_Subscription_StatusDetails extends Braintree_Instance
|
18 |
+
{
|
19 |
+
}
|
lib/Braintree/SubscriptionGateway.php
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree SubscriptionGateway module
|
4 |
+
*
|
5 |
+
* <b>== More information ==</b>
|
6 |
+
*
|
7 |
+
* For more detailed information on Subscriptions, see {@link http://www.braintreepayments.com/gateway/subscription-api http://www.braintreepaymentsolutions.com/gateway/subscription-api}
|
8 |
+
*
|
9 |
+
* PHP Version 5
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_SubscriptionGateway
|
15 |
+
{
|
16 |
+
private $_gateway;
|
17 |
+
private $_config;
|
18 |
+
private $_http;
|
19 |
+
|
20 |
+
public function __construct($gateway)
|
21 |
+
{
|
22 |
+
$this->_gateway = $gateway;
|
23 |
+
$this->_config = $gateway->config;
|
24 |
+
$this->_http = new Braintree_Http($gateway->config);
|
25 |
+
}
|
26 |
+
|
27 |
+
public function create($attributes)
|
28 |
+
{
|
29 |
+
Braintree_Util::verifyKeys(self::_createSignature(), $attributes);
|
30 |
+
$path = $this->_config->merchantPath() . '/subscriptions';
|
31 |
+
$response = $this->_http->post($path, array('subscription' => $attributes));
|
32 |
+
return $this->_verifyGatewayResponse($response);
|
33 |
+
}
|
34 |
+
|
35 |
+
public function find($id)
|
36 |
+
{
|
37 |
+
$this->_validateId($id);
|
38 |
+
|
39 |
+
try {
|
40 |
+
$path = $this->_config->merchantPath() . '/subscriptions/' . $id;
|
41 |
+
$response = $this->_http->get($path);
|
42 |
+
return Braintree_Subscription::factory($response['subscription']);
|
43 |
+
} catch (Braintree_Exception_NotFound $e) {
|
44 |
+
throw new Braintree_Exception_NotFound('subscription with id ' . $id . ' not found');
|
45 |
+
}
|
46 |
+
|
47 |
+
}
|
48 |
+
|
49 |
+
public function search($query)
|
50 |
+
{
|
51 |
+
$criteria = array();
|
52 |
+
foreach ($query as $term) {
|
53 |
+
$criteria[$term->name] = $term->toparam();
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
$path = $this->_config->merchantPath() . '/subscriptions/advanced_search_ids';
|
58 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
59 |
+
$pager = array(
|
60 |
+
'object' => $this,
|
61 |
+
'method' => 'fetch',
|
62 |
+
'methodArgs' => array($query)
|
63 |
+
);
|
64 |
+
|
65 |
+
return new Braintree_ResourceCollection($response, $pager);
|
66 |
+
}
|
67 |
+
|
68 |
+
public function fetch($query, $ids)
|
69 |
+
{
|
70 |
+
$criteria = array();
|
71 |
+
foreach ($query as $term) {
|
72 |
+
$criteria[$term->name] = $term->toparam();
|
73 |
+
}
|
74 |
+
$criteria["ids"] = Braintree_SubscriptionSearch::ids()->in($ids)->toparam();
|
75 |
+
$path = $this->_config->merchantPath() . '/subscriptions/advanced_search';
|
76 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
77 |
+
|
78 |
+
return Braintree_Util::extractAttributeAsArray(
|
79 |
+
$response['subscriptions'],
|
80 |
+
'subscription'
|
81 |
+
);
|
82 |
+
}
|
83 |
+
|
84 |
+
public function update($subscriptionId, $attributes)
|
85 |
+
{
|
86 |
+
Braintree_Util::verifyKeys(self::_updateSignature(), $attributes);
|
87 |
+
$path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId;
|
88 |
+
$response = $this->_http->put($path, array('subscription' => $attributes));
|
89 |
+
return $this->_verifyGatewayResponse($response);
|
90 |
+
}
|
91 |
+
|
92 |
+
public function retryCharge($subscriptionId, $amount = null)
|
93 |
+
{
|
94 |
+
$transaction_params = array('type' => Braintree_Transaction::SALE,
|
95 |
+
'subscriptionId' => $subscriptionId);
|
96 |
+
if (isset($amount)) {
|
97 |
+
$transaction_params['amount'] = $amount;
|
98 |
+
}
|
99 |
+
|
100 |
+
$path = $this->_config->merchantPath() . '/transactions';
|
101 |
+
$response = $this->_http->post($path, array('transaction' => $transaction_params));
|
102 |
+
return $this->_verifyGatewayResponse($response);
|
103 |
+
}
|
104 |
+
|
105 |
+
public function cancel($subscriptionId)
|
106 |
+
{
|
107 |
+
$path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId . '/cancel';
|
108 |
+
$response = $this->_http->put($path);
|
109 |
+
return $this->_verifyGatewayResponse($response);
|
110 |
+
}
|
111 |
+
|
112 |
+
private static function _createSignature()
|
113 |
+
{
|
114 |
+
return array_merge(
|
115 |
+
array(
|
116 |
+
'billingDayOfMonth',
|
117 |
+
'firstBillingDate',
|
118 |
+
'createdAt',
|
119 |
+
'updatedAt',
|
120 |
+
'id',
|
121 |
+
'merchantAccountId',
|
122 |
+
'neverExpires',
|
123 |
+
'numberOfBillingCycles',
|
124 |
+
'paymentMethodToken',
|
125 |
+
'paymentMethodNonce',
|
126 |
+
'planId',
|
127 |
+
'price',
|
128 |
+
'trialDuration',
|
129 |
+
'trialDurationUnit',
|
130 |
+
'trialPeriod',
|
131 |
+
array('descriptor' => array('name', 'phone', 'url')),
|
132 |
+
array('options' => array('doNotInheritAddOnsOrDiscounts', 'startImmediately')),
|
133 |
+
),
|
134 |
+
self::_addOnDiscountSignature()
|
135 |
+
);
|
136 |
+
}
|
137 |
+
|
138 |
+
private static function _updateSignature()
|
139 |
+
{
|
140 |
+
return array_merge(
|
141 |
+
array(
|
142 |
+
'merchantAccountId', 'numberOfBillingCycles', 'paymentMethodToken', 'planId',
|
143 |
+
'paymentMethodNonce', 'id', 'neverExpires', 'price',
|
144 |
+
array('descriptor' => array('name', 'phone', 'url')),
|
145 |
+
array('options' => array('prorateCharges', 'replaceAllAddOnsAndDiscounts', 'revertSubscriptionOnProrationFailure')),
|
146 |
+
),
|
147 |
+
self::_addOnDiscountSignature()
|
148 |
+
);
|
149 |
+
}
|
150 |
+
|
151 |
+
private static function _addOnDiscountSignature()
|
152 |
+
{
|
153 |
+
return array(
|
154 |
+
array(
|
155 |
+
'addOns' => array(
|
156 |
+
array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
|
157 |
+
array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
|
158 |
+
array('remove' => array('_anyKey_')),
|
159 |
+
)
|
160 |
+
),
|
161 |
+
array(
|
162 |
+
'discounts' => array(
|
163 |
+
array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
|
164 |
+
array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
|
165 |
+
array('remove' => array('_anyKey_')),
|
166 |
+
)
|
167 |
+
)
|
168 |
+
);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @ignore
|
173 |
+
*/
|
174 |
+
private function _validateId($id = null) {
|
175 |
+
if (empty($id)) {
|
176 |
+
throw new InvalidArgumentException(
|
177 |
+
'expected subscription id to be set'
|
178 |
+
);
|
179 |
+
}
|
180 |
+
if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
|
181 |
+
throw new InvalidArgumentException(
|
182 |
+
$id . ' is an invalid subscription id.'
|
183 |
+
);
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* @ignore
|
189 |
+
*/
|
190 |
+
private function _verifyGatewayResponse($response)
|
191 |
+
{
|
192 |
+
if (isset($response['subscription'])) {
|
193 |
+
return new Braintree_Result_Successful(
|
194 |
+
Braintree_Subscription::factory($response['subscription'])
|
195 |
+
);
|
196 |
+
} else if (isset($response['transaction'])) {
|
197 |
+
// return a populated instance of Braintree_Transaction, for subscription retryCharge
|
198 |
+
return new Braintree_Result_Successful(
|
199 |
+
Braintree_Transaction::factory($response['transaction'])
|
200 |
+
);
|
201 |
+
} else if (isset($response['apiErrorResponse'])) {
|
202 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
203 |
+
} else {
|
204 |
+
throw new Braintree_Exception_Unexpected(
|
205 |
+
"Expected subscription, transaction, or apiErrorResponse"
|
206 |
+
);
|
207 |
+
}
|
208 |
+
}
|
209 |
+
}
|
lib/Braintree/SubscriptionSearch.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_SubscriptionSearch
|
3 |
+
{
|
4 |
+
static function billingCyclesRemaining()
|
5 |
+
{
|
6 |
+
return new Braintree_RangeNode('billing_cycles_remaining');
|
7 |
+
}
|
8 |
+
|
9 |
+
static function daysPastDue()
|
10 |
+
{
|
11 |
+
return new Braintree_RangeNode('days_past_due');
|
12 |
+
}
|
13 |
+
|
14 |
+
static function id()
|
15 |
+
{
|
16 |
+
return new Braintree_TextNode('id');
|
17 |
+
}
|
18 |
+
|
19 |
+
static function inTrialPeriod()
|
20 |
+
{
|
21 |
+
return new Braintree_MultipleValueNode('in_trial_period', array(true, false));
|
22 |
+
}
|
23 |
+
|
24 |
+
static function merchantAccountId()
|
25 |
+
{
|
26 |
+
return new Braintree_MultipleValueNode('merchant_account_id');
|
27 |
+
}
|
28 |
+
|
29 |
+
static function nextBillingDate()
|
30 |
+
{
|
31 |
+
return new Braintree_RangeNode('next_billing_date');
|
32 |
+
}
|
33 |
+
|
34 |
+
static function planId()
|
35 |
+
{
|
36 |
+
return new Braintree_MultipleValueOrTextNode('plan_id');
|
37 |
+
}
|
38 |
+
|
39 |
+
static function price()
|
40 |
+
{
|
41 |
+
return new Braintree_RangeNode('price');
|
42 |
+
}
|
43 |
+
|
44 |
+
static function status()
|
45 |
+
{
|
46 |
+
return new Braintree_MultipleValueNode("status", array(
|
47 |
+
Braintree_Subscription::ACTIVE,
|
48 |
+
Braintree_Subscription::CANCELED,
|
49 |
+
Braintree_Subscription::EXPIRED,
|
50 |
+
Braintree_Subscription::PAST_DUE,
|
51 |
+
Braintree_Subscription::PENDING
|
52 |
+
));
|
53 |
+
}
|
54 |
+
|
55 |
+
static function transactionId()
|
56 |
+
{
|
57 |
+
return new Braintree_TextNode('transaction_id');
|
58 |
+
}
|
59 |
+
|
60 |
+
static function ids()
|
61 |
+
{
|
62 |
+
return new Braintree_MultipleValueNode('ids');
|
63 |
+
}
|
64 |
+
}
|
lib/Braintree/Test/CreditCardNumbers.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Credit card information used for testing purposes
|
5 |
+
*
|
6 |
+
* The constants contained in the Braintree_Test_CreditCardNumbers class provide
|
7 |
+
* credit card numbers that should be used when working in the sandbox environment.
|
8 |
+
* The sandbox will not accept any credit card numbers other than the ones listed below.
|
9 |
+
*
|
10 |
+
* @package Braintree
|
11 |
+
* @subpackage Test
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_Test_CreditCardNumbers
|
15 |
+
{
|
16 |
+
public static $amExes = array(
|
17 |
+
'378282246310005',
|
18 |
+
'371449635398431',
|
19 |
+
'378734493671000',
|
20 |
+
);
|
21 |
+
public static $carteBlanches = array('30569309025904',);
|
22 |
+
public static $dinersClubs = array('38520000023237',);
|
23 |
+
public static $discoverCards = array(
|
24 |
+
'6011111111111117',
|
25 |
+
'6011000990139424',
|
26 |
+
);
|
27 |
+
public static $JCBs = array(
|
28 |
+
'3530111333300000',
|
29 |
+
'3566002020360505',
|
30 |
+
);
|
31 |
+
|
32 |
+
public static $masterCard = '5555555555554444';
|
33 |
+
public static $masterCardInternational = '5105105105105100';
|
34 |
+
public static $masterCards = array(
|
35 |
+
'5105105105105100',
|
36 |
+
'5555555555554444',
|
37 |
+
);
|
38 |
+
|
39 |
+
public static $visa = '4012888888881881';
|
40 |
+
public static $visaInternational = '4009348888881881';
|
41 |
+
public static $visas = array(
|
42 |
+
'4009348888881881',
|
43 |
+
'4012888888881881',
|
44 |
+
'4111111111111111',
|
45 |
+
'4000111111111115',
|
46 |
+
);
|
47 |
+
|
48 |
+
public static $unknowns = array(
|
49 |
+
'1000000000000008',
|
50 |
+
);
|
51 |
+
|
52 |
+
public static $failsSandboxVerification = array(
|
53 |
+
'AmEx' => '378734493671000',
|
54 |
+
'Discover' => '6011000990139424',
|
55 |
+
'MasterCard' => '5105105105105100',
|
56 |
+
'Visa' => '4000111111111115',
|
57 |
+
);
|
58 |
+
|
59 |
+
|
60 |
+
public static function getAll()
|
61 |
+
{
|
62 |
+
return array_merge(
|
63 |
+
self::$amExes,
|
64 |
+
self::$discoverCards,
|
65 |
+
self::$masterCards,
|
66 |
+
self::$visas
|
67 |
+
);
|
68 |
+
}
|
69 |
+
}
|
lib/Braintree/Test/MerchantAccount.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Merchant Account constants used for testing purposes
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Test
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Test_MerchantAccount
|
10 |
+
{
|
11 |
+
public static $approve = "approve_me";
|
12 |
+
|
13 |
+
public static $insufficientFundsContactUs = "insufficient_funds__contact";
|
14 |
+
public static $accountNotAuthorizedContactUs = "account_not_authorized__contact";
|
15 |
+
public static $bankRejectedUpdateFundingInformation = "bank_rejected__update";
|
16 |
+
public static $bankRejectedNone = "bank_rejected__none";
|
17 |
+
|
18 |
+
|
19 |
+
}
|
lib/Braintree/Test/Nonces.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Nonces used for testing purposes
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Test
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Nonces used for testing purposes
|
12 |
+
*
|
13 |
+
* The constants in this class can be used to perform nonce operations
|
14 |
+
* with the desired status in the sandbox environment.
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @subpackage Test
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*/
|
20 |
+
class Braintree_Test_Nonces
|
21 |
+
{
|
22 |
+
public static $transactable = "fake-valid-nonce";
|
23 |
+
public static $consumed = "fake-consumed-nonce";
|
24 |
+
public static $paypalOneTimePayment = "fake-paypal-one-time-nonce";
|
25 |
+
public static $paypalFuturePayment = "fake-paypal-future-nonce";
|
26 |
+
public static $applePayVisa = "fake-apple-pay-visa-nonce";
|
27 |
+
public static $applePayMasterCard = "fake-apple-pay-visa-nonce";
|
28 |
+
public static $applePayAmEx = "fake-apple-pay-amex-nonce";
|
29 |
+
public static $abstractTransactable = "fake-abstract-transactable-nonce";
|
30 |
+
public static $coinbase = "fake-coinbase-nonce";
|
31 |
+
}
|
lib/Braintree/Test/TransactionAmounts.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Transaction amounts used for testing purposes
|
5 |
+
*
|
6 |
+
* The constants in this class can be used to create transactions with
|
7 |
+
* the desired status in the sandbox environment.
|
8 |
+
*
|
9 |
+
* @package Braintree
|
10 |
+
* @subpackage Test
|
11 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
12 |
+
*/
|
13 |
+
class Braintree_Test_TransactionAmounts
|
14 |
+
{
|
15 |
+
public static $authorize = '1000.00';
|
16 |
+
public static $decline = '2000.00';
|
17 |
+
}
|
lib/Braintree/Test/VenmoSdk.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* VenmoSdk payment method codes used for testing purposes
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Test
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
class Braintree_Test_VenmoSdk
|
10 |
+
{
|
11 |
+
public static $visaPaymentMethodCode = "stub-4111111111111111";
|
12 |
+
|
13 |
+
public static function generateTestPaymentMethodCode($number) {
|
14 |
+
return "stub-" . $number;
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function getInvalidPaymentMethodCode() {
|
18 |
+
return "stub-invalid-payment-method-code";
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getTestSession() {
|
22 |
+
return "stub-session";
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function getInvalidTestSession() {
|
26 |
+
return "stub-invalid-session";
|
27 |
+
}
|
28 |
+
}
|
lib/Braintree/TextNode.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Braintree_TextNode extends Braintree_PartialMatchNode
|
4 |
+
{
|
5 |
+
function contains($value)
|
6 |
+
{
|
7 |
+
$this->searchTerms["contains"] = strval($value);
|
8 |
+
return $this;
|
9 |
+
}
|
10 |
+
}
|
lib/Braintree/Transaction.php
ADDED
@@ -0,0 +1,504 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Transaction processor
|
4 |
+
* Creates and manages transactions
|
5 |
+
*
|
6 |
+
* At minimum, an amount, credit card number, and
|
7 |
+
* credit card expiration date are required.
|
8 |
+
*
|
9 |
+
* <b>Minimalistic example:</b>
|
10 |
+
* <code>
|
11 |
+
* Braintree_Transaction::saleNoValidate(array(
|
12 |
+
* 'amount' => '100.00',
|
13 |
+
* 'creditCard' => array(
|
14 |
+
* 'number' => '5105105105105100',
|
15 |
+
* 'expirationDate' => '05/12',
|
16 |
+
* ),
|
17 |
+
* ));
|
18 |
+
* </code>
|
19 |
+
*
|
20 |
+
* <b>Full example:</b>
|
21 |
+
* <code>
|
22 |
+
* Braintree_Transaction::saleNoValidate(array(
|
23 |
+
* 'amount' => '100.00',
|
24 |
+
* 'orderId' => '123',
|
25 |
+
* 'channel' => 'MyShoppingCardProvider',
|
26 |
+
* 'creditCard' => array(
|
27 |
+
* // if token is omitted, the gateway will generate a token
|
28 |
+
* 'token' => 'credit_card_123',
|
29 |
+
* 'number' => '5105105105105100',
|
30 |
+
* 'expirationDate' => '05/2011',
|
31 |
+
* 'cvv' => '123',
|
32 |
+
* ),
|
33 |
+
* 'customer' => array(
|
34 |
+
* // if id is omitted, the gateway will generate an id
|
35 |
+
* 'id' => 'customer_123',
|
36 |
+
* 'firstName' => 'Dan',
|
37 |
+
* 'lastName' => 'Smith',
|
38 |
+
* 'company' => 'Braintree',
|
39 |
+
* 'email' => 'dan@example.com',
|
40 |
+
* 'phone' => '419-555-1234',
|
41 |
+
* 'fax' => '419-555-1235',
|
42 |
+
* 'website' => 'http://braintreepayments.com'
|
43 |
+
* ),
|
44 |
+
* 'billing' => array(
|
45 |
+
* 'firstName' => 'Carl',
|
46 |
+
* 'lastName' => 'Jones',
|
47 |
+
* 'company' => 'Braintree',
|
48 |
+
* 'streetAddress' => '123 E Main St',
|
49 |
+
* 'extendedAddress' => 'Suite 403',
|
50 |
+
* 'locality' => 'Chicago',
|
51 |
+
* 'region' => 'IL',
|
52 |
+
* 'postalCode' => '60622',
|
53 |
+
* 'countryName' => 'United States of America'
|
54 |
+
* ),
|
55 |
+
* 'shipping' => array(
|
56 |
+
* 'firstName' => 'Andrew',
|
57 |
+
* 'lastName' => 'Mason',
|
58 |
+
* 'company' => 'Braintree',
|
59 |
+
* 'streetAddress' => '456 W Main St',
|
60 |
+
* 'extendedAddress' => 'Apt 2F',
|
61 |
+
* 'locality' => 'Bartlett',
|
62 |
+
* 'region' => 'IL',
|
63 |
+
* 'postalCode' => '60103',
|
64 |
+
* 'countryName' => 'United States of America'
|
65 |
+
* ),
|
66 |
+
* 'customFields' => array(
|
67 |
+
* 'birthdate' => '11/13/1954'
|
68 |
+
* )
|
69 |
+
* )
|
70 |
+
* </code>
|
71 |
+
*
|
72 |
+
* <b>== Storing in the Vault ==</b>
|
73 |
+
*
|
74 |
+
* The customer and credit card information used for
|
75 |
+
* a transaction can be stored in the vault by setting
|
76 |
+
* <i>transaction[options][storeInVault]</i> to true.
|
77 |
+
* <code>
|
78 |
+
* $transaction = Braintree_Transaction::saleNoValidate(array(
|
79 |
+
* 'customer' => array(
|
80 |
+
* 'firstName' => 'Adam',
|
81 |
+
* 'lastName' => 'Williams'
|
82 |
+
* ),
|
83 |
+
* 'creditCard' => array(
|
84 |
+
* 'number' => '5105105105105100',
|
85 |
+
* 'expirationDate' => '05/2012'
|
86 |
+
* ),
|
87 |
+
* 'options' => array(
|
88 |
+
* 'storeInVault' => true
|
89 |
+
* )
|
90 |
+
* ));
|
91 |
+
*
|
92 |
+
* echo $transaction->customerDetails->id
|
93 |
+
* // '865534'
|
94 |
+
* echo $transaction->creditCardDetails->token
|
95 |
+
* // '6b6m'
|
96 |
+
* </code>
|
97 |
+
*
|
98 |
+
* To also store the billing address in the vault, pass the
|
99 |
+
* <b>addBillingAddressToPaymentMethod</b> option.
|
100 |
+
* <code>
|
101 |
+
* Braintree_Transaction.saleNoValidate(array(
|
102 |
+
* ...
|
103 |
+
* 'options' => array(
|
104 |
+
* 'storeInVault' => true
|
105 |
+
* 'addBillingAddressToPaymentMethod' => true
|
106 |
+
* )
|
107 |
+
* ));
|
108 |
+
* </code>
|
109 |
+
*
|
110 |
+
* <b>== Submitting for Settlement==</b>
|
111 |
+
*
|
112 |
+
* This can only be done when the transction's
|
113 |
+
* status is <b>authorized</b>. If <b>amount</b> is not specified,
|
114 |
+
* the full authorized amount will be settled. If you would like to settle
|
115 |
+
* less than the full authorized amount, pass the desired amount.
|
116 |
+
* You cannot settle more than the authorized amount.
|
117 |
+
*
|
118 |
+
* A transaction can be submitted for settlement when created by setting
|
119 |
+
* $transaction[options][submitForSettlement] to true.
|
120 |
+
*
|
121 |
+
* <code>
|
122 |
+
* $transaction = Braintree_Transaction::saleNoValidate(array(
|
123 |
+
* 'amount' => '100.00',
|
124 |
+
* 'creditCard' => array(
|
125 |
+
* 'number' => '5105105105105100',
|
126 |
+
* 'expirationDate' => '05/2012'
|
127 |
+
* ),
|
128 |
+
* 'options' => array(
|
129 |
+
* 'submitForSettlement' => true
|
130 |
+
* )
|
131 |
+
* ));
|
132 |
+
* </code>
|
133 |
+
*
|
134 |
+
* <b>== More information ==</b>
|
135 |
+
*
|
136 |
+
* For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api}
|
137 |
+
*
|
138 |
+
* @package Braintree
|
139 |
+
* @category Resources
|
140 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
141 |
+
*
|
142 |
+
*
|
143 |
+
* @property-read string $avsErrorResponseCode
|
144 |
+
* @property-read string $avsPostalCodeResponseCode
|
145 |
+
* @property-read string $avsStreetAddressResponseCode
|
146 |
+
* @property-read string $cvvResponseCode
|
147 |
+
* @property-read string $id transaction id
|
148 |
+
* @property-read string $amount transaction amount
|
149 |
+
* @property-read object $billingDetails transaction billing address
|
150 |
+
* @property-read string $createdAt transaction created timestamp
|
151 |
+
* @property-read object $applePayCardDetails transaction Apple Pay card info
|
152 |
+
* @property-read object $creditCardDetails transaction credit card info
|
153 |
+
* @property-read object $coinbaseDetails transaction Coinbase account info
|
154 |
+
* @property-read object $paypalDetails transaction paypal account info
|
155 |
+
* @property-read object $customerDetails transaction customer info
|
156 |
+
* @property-read array $customFields custom fields passed with the request
|
157 |
+
* @property-read string $processorResponseCode gateway response code
|
158 |
+
* @property-read string $additionalProcessorResponse raw response from processor
|
159 |
+
* @property-read object $shippingDetails transaction shipping address
|
160 |
+
* @property-read string $status transaction status
|
161 |
+
* @property-read array $statusHistory array of StatusDetails objects
|
162 |
+
* @property-read string $type transaction type
|
163 |
+
* @property-read string $updatedAt transaction updated timestamp
|
164 |
+
* @property-read object $disbursementDetails populated when transaction is disbursed
|
165 |
+
* @property-read object $disputes populated when transaction is disputed
|
166 |
+
*
|
167 |
+
*/
|
168 |
+
|
169 |
+
final class Braintree_Transaction extends Braintree
|
170 |
+
{
|
171 |
+
// Transaction Status
|
172 |
+
const AUTHORIZATION_EXPIRED = 'authorization_expired';
|
173 |
+
const AUTHORIZING = 'authorizing';
|
174 |
+
const AUTHORIZED = 'authorized';
|
175 |
+
const GATEWAY_REJECTED = 'gateway_rejected';
|
176 |
+
const FAILED = 'failed';
|
177 |
+
const PROCESSOR_DECLINED = 'processor_declined';
|
178 |
+
const SETTLED = 'settled';
|
179 |
+
const SETTLING = 'settling';
|
180 |
+
const SUBMITTED_FOR_SETTLEMENT = 'submitted_for_settlement';
|
181 |
+
const VOIDED = 'voided';
|
182 |
+
const UNRECOGNIZED = 'unrecognized';
|
183 |
+
const SETTLEMENT_DECLINED = 'settlement_declined';
|
184 |
+
const SETTLEMENT_PENDING = 'settlement_pending';
|
185 |
+
|
186 |
+
// Transaction Escrow Status
|
187 |
+
const ESCROW_HOLD_PENDING = 'hold_pending';
|
188 |
+
const ESCROW_HELD = 'held';
|
189 |
+
const ESCROW_RELEASE_PENDING = 'release_pending';
|
190 |
+
const ESCROW_RELEASED = 'released';
|
191 |
+
const ESCROW_REFUNDED = 'refunded';
|
192 |
+
|
193 |
+
// Transaction Types
|
194 |
+
const SALE = 'sale';
|
195 |
+
const CREDIT = 'credit';
|
196 |
+
|
197 |
+
// Transaction Created Using
|
198 |
+
const FULL_INFORMATION = 'full_information';
|
199 |
+
const TOKEN = 'token';
|
200 |
+
|
201 |
+
// Transaction Sources
|
202 |
+
const API = 'api';
|
203 |
+
const CONTROL_PANEL = 'control_panel';
|
204 |
+
const RECURRING = 'recurring';
|
205 |
+
|
206 |
+
// Gateway Rejection Reason
|
207 |
+
const AVS = 'avs';
|
208 |
+
const AVS_AND_CVV = 'avs_and_cvv';
|
209 |
+
const CVV = 'cvv';
|
210 |
+
const DUPLICATE = 'duplicate';
|
211 |
+
const FRAUD = 'fraud';
|
212 |
+
const THREE_D_SECURE = 'three_d_secure';
|
213 |
+
|
214 |
+
// Industry Types
|
215 |
+
const LODGING_INDUSTRY = 'lodging';
|
216 |
+
const TRAVEL_AND_CRUISE_INDUSTRY = 'travel_cruise';
|
217 |
+
|
218 |
+
/**
|
219 |
+
* sets instance properties from an array of values
|
220 |
+
*
|
221 |
+
* @ignore
|
222 |
+
* @access protected
|
223 |
+
* @param array $transactionAttribs array of transaction data
|
224 |
+
* @return none
|
225 |
+
*/
|
226 |
+
protected function _initialize($transactionAttribs)
|
227 |
+
{
|
228 |
+
$this->_attributes = $transactionAttribs;
|
229 |
+
|
230 |
+
if (isset($transactionAttribs['applePay'])) {
|
231 |
+
$this->_set('applePayCardDetails',
|
232 |
+
new Braintree_Transaction_ApplePayCardDetails(
|
233 |
+
$transactionAttribs['applePay']
|
234 |
+
)
|
235 |
+
);
|
236 |
+
}
|
237 |
+
|
238 |
+
if (isset($transactionAttribs['creditCard'])) {
|
239 |
+
$this->_set('creditCardDetails',
|
240 |
+
new Braintree_Transaction_CreditCardDetails(
|
241 |
+
$transactionAttribs['creditCard']
|
242 |
+
)
|
243 |
+
);
|
244 |
+
}
|
245 |
+
|
246 |
+
if (isset($transactionAttribs['coinbaseAccount'])) {
|
247 |
+
$this->_set('coinbaseDetails',
|
248 |
+
new Braintree_Transaction_CoinbaseDetails(
|
249 |
+
$transactionAttribs['coinbaseAccount']
|
250 |
+
)
|
251 |
+
);
|
252 |
+
}
|
253 |
+
|
254 |
+
if (isset($transactionAttribs['paypal'])) {
|
255 |
+
$this->_set('paypalDetails',
|
256 |
+
new Braintree_Transaction_PayPalDetails(
|
257 |
+
$transactionAttribs['paypal']
|
258 |
+
)
|
259 |
+
);
|
260 |
+
}
|
261 |
+
|
262 |
+
if (isset($transactionAttribs['customer'])) {
|
263 |
+
$this->_set('customerDetails',
|
264 |
+
new Braintree_Transaction_CustomerDetails(
|
265 |
+
$transactionAttribs['customer']
|
266 |
+
)
|
267 |
+
);
|
268 |
+
}
|
269 |
+
|
270 |
+
if (isset($transactionAttribs['billing'])) {
|
271 |
+
$this->_set('billingDetails',
|
272 |
+
new Braintree_Transaction_AddressDetails(
|
273 |
+
$transactionAttribs['billing']
|
274 |
+
)
|
275 |
+
);
|
276 |
+
}
|
277 |
+
|
278 |
+
if (isset($transactionAttribs['shipping'])) {
|
279 |
+
$this->_set('shippingDetails',
|
280 |
+
new Braintree_Transaction_AddressDetails(
|
281 |
+
$transactionAttribs['shipping']
|
282 |
+
)
|
283 |
+
);
|
284 |
+
}
|
285 |
+
|
286 |
+
if (isset($transactionAttribs['subscription'])) {
|
287 |
+
$this->_set('subscriptionDetails',
|
288 |
+
new Braintree_Transaction_SubscriptionDetails(
|
289 |
+
$transactionAttribs['subscription']
|
290 |
+
)
|
291 |
+
);
|
292 |
+
}
|
293 |
+
|
294 |
+
if (isset($transactionAttribs['descriptor'])) {
|
295 |
+
$this->_set('descriptor',
|
296 |
+
new Braintree_Descriptor(
|
297 |
+
$transactionAttribs['descriptor']
|
298 |
+
)
|
299 |
+
);
|
300 |
+
}
|
301 |
+
|
302 |
+
if (isset($transactionAttribs['disbursementDetails'])) {
|
303 |
+
$this->_set('disbursementDetails',
|
304 |
+
new Braintree_DisbursementDetails($transactionAttribs['disbursementDetails'])
|
305 |
+
);
|
306 |
+
}
|
307 |
+
|
308 |
+
$disputes = array();
|
309 |
+
if (isset($transactionAttribs['disputes'])) {
|
310 |
+
foreach ($transactionAttribs['disputes'] AS $dispute) {
|
311 |
+
$disputes[] = Braintree_Dispute::factory($dispute);
|
312 |
+
}
|
313 |
+
}
|
314 |
+
|
315 |
+
$this->_set('disputes', $disputes);
|
316 |
+
|
317 |
+
$statusHistory = array();
|
318 |
+
if (isset($transactionAttribs['statusHistory'])) {
|
319 |
+
foreach ($transactionAttribs['statusHistory'] AS $history) {
|
320 |
+
$statusHistory[] = new Braintree_Transaction_StatusDetails($history);
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
$this->_set('statusHistory', $statusHistory);
|
325 |
+
|
326 |
+
$addOnArray = array();
|
327 |
+
if (isset($transactionAttribs['addOns'])) {
|
328 |
+
foreach ($transactionAttribs['addOns'] AS $addOn) {
|
329 |
+
$addOnArray[] = Braintree_AddOn::factory($addOn);
|
330 |
+
}
|
331 |
+
}
|
332 |
+
$this->_set('addOns', $addOnArray);
|
333 |
+
|
334 |
+
$discountArray = array();
|
335 |
+
if (isset($transactionAttribs['discounts'])) {
|
336 |
+
foreach ($transactionAttribs['discounts'] AS $discount) {
|
337 |
+
$discountArray[] = Braintree_Discount::factory($discount);
|
338 |
+
}
|
339 |
+
}
|
340 |
+
$this->_set('discounts', $discountArray);
|
341 |
+
|
342 |
+
if(isset($transactionAttribs['riskData'])) {
|
343 |
+
$this->_set('riskData', Braintree_RiskData::factory($transactionAttribs['riskData']));
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* returns a string representation of the transaction
|
349 |
+
* @return string
|
350 |
+
*/
|
351 |
+
public function __toString()
|
352 |
+
{
|
353 |
+
// array of attributes to print
|
354 |
+
$display = array(
|
355 |
+
'id', 'type', 'amount', 'status',
|
356 |
+
'createdAt', 'creditCardDetails', 'customerDetails'
|
357 |
+
);
|
358 |
+
|
359 |
+
$displayAttributes = array();
|
360 |
+
foreach ($display AS $attrib) {
|
361 |
+
$displayAttributes[$attrib] = $this->$attrib;
|
362 |
+
}
|
363 |
+
return __CLASS__ . '[' .
|
364 |
+
Braintree_Util::attributesToString($displayAttributes) .']';
|
365 |
+
}
|
366 |
+
|
367 |
+
public function isEqual($otherTx)
|
368 |
+
{
|
369 |
+
return $this->id === $otherTx->id;
|
370 |
+
}
|
371 |
+
|
372 |
+
public function vaultCreditCard()
|
373 |
+
{
|
374 |
+
$token = $this->creditCardDetails->token;
|
375 |
+
if (empty($token)) {
|
376 |
+
return null;
|
377 |
+
}
|
378 |
+
else {
|
379 |
+
return Braintree_CreditCard::find($token);
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
public function vaultCustomer()
|
384 |
+
{
|
385 |
+
$customerId = $this->customerDetails->id;
|
386 |
+
if (empty($customerId)) {
|
387 |
+
return null;
|
388 |
+
}
|
389 |
+
else {
|
390 |
+
return Braintree_Customer::find($customerId);
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
public function isDisbursed() {
|
395 |
+
return $this->disbursementDetails->isValid();
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* factory method: returns an instance of Braintree_Transaction
|
400 |
+
* to the requesting method, with populated properties
|
401 |
+
*
|
402 |
+
* @ignore
|
403 |
+
* @return object instance of Braintree_Transaction
|
404 |
+
*/
|
405 |
+
public static function factory($attributes)
|
406 |
+
{
|
407 |
+
$instance = new self();
|
408 |
+
$instance->_initialize($attributes);
|
409 |
+
return $instance;
|
410 |
+
}
|
411 |
+
|
412 |
+
|
413 |
+
// static methods redirecting to gateway
|
414 |
+
|
415 |
+
public static function cloneTransaction($transactionId, $attribs)
|
416 |
+
{
|
417 |
+
return Braintree_Configuration::gateway()->transaction()->cloneTransaction($transactionId, $attribs);
|
418 |
+
}
|
419 |
+
|
420 |
+
public static function createFromTransparentRedirect($queryString)
|
421 |
+
{
|
422 |
+
return Braintree_Configuration::gateway()->transaction()->createFromTransparentRedirect($queryString);
|
423 |
+
}
|
424 |
+
|
425 |
+
public static function createTransactionUrl()
|
426 |
+
{
|
427 |
+
return Braintree_Configuration::gateway()->transaction()->createTransactionUrl();
|
428 |
+
}
|
429 |
+
|
430 |
+
public static function credit($attribs)
|
431 |
+
{
|
432 |
+
return Braintree_Configuration::gateway()->transaction()->credit($attribs);
|
433 |
+
}
|
434 |
+
|
435 |
+
public static function creditNoValidate($attribs)
|
436 |
+
{
|
437 |
+
return Braintree_Configuration::gateway()->transaction()->creditNoValidate($attribs);
|
438 |
+
}
|
439 |
+
|
440 |
+
public static function find($id)
|
441 |
+
{
|
442 |
+
return Braintree_Configuration::gateway()->transaction()->find($id);
|
443 |
+
}
|
444 |
+
|
445 |
+
public static function sale($attribs)
|
446 |
+
{
|
447 |
+
return Braintree_Configuration::gateway()->transaction()->sale($attribs);
|
448 |
+
}
|
449 |
+
|
450 |
+
public static function saleNoValidate($attribs)
|
451 |
+
{
|
452 |
+
return Braintree_Configuration::gateway()->transaction()->saleNoValidate($attribs);
|
453 |
+
}
|
454 |
+
|
455 |
+
public static function search($query)
|
456 |
+
{
|
457 |
+
return Braintree_Configuration::gateway()->transaction()->search($query);
|
458 |
+
}
|
459 |
+
|
460 |
+
public static function fetch($query, $ids)
|
461 |
+
{
|
462 |
+
return Braintree_Configuration::gateway()->transaction()->fetch($query, $ids);
|
463 |
+
}
|
464 |
+
|
465 |
+
public static function void($transactionId)
|
466 |
+
{
|
467 |
+
return Braintree_Configuration::gateway()->transaction()->void($transactionId);
|
468 |
+
}
|
469 |
+
|
470 |
+
public static function voidNoValidate($transactionId)
|
471 |
+
{
|
472 |
+
return Braintree_Configuration::gateway()->transaction()->voidNoValidate($transactionId);
|
473 |
+
}
|
474 |
+
|
475 |
+
public static function submitForSettlement($transactionId, $amount = null)
|
476 |
+
{
|
477 |
+
return Braintree_Configuration::gateway()->transaction()->submitForSettlement($transactionId, $amount);
|
478 |
+
}
|
479 |
+
|
480 |
+
public static function submitForSettlementNoValidate($transactionId, $amount = null)
|
481 |
+
{
|
482 |
+
return Braintree_Configuration::gateway()->transaction()->submitForSettlementNoValidate($transactionId, $amount);
|
483 |
+
}
|
484 |
+
|
485 |
+
public static function holdInEscrow($transactionId)
|
486 |
+
{
|
487 |
+
return Braintree_Configuration::gateway()->transaction()->holdInEscrow($transactionId);
|
488 |
+
}
|
489 |
+
|
490 |
+
public static function releaseFromEscrow($transactionId)
|
491 |
+
{
|
492 |
+
return Braintree_Configuration::gateway()->transaction()->releaseFromEscrow($transactionId);
|
493 |
+
}
|
494 |
+
|
495 |
+
public static function cancelRelease($transactionId)
|
496 |
+
{
|
497 |
+
return Braintree_Configuration::gateway()->transaction()->cancelRelease($transactionId);
|
498 |
+
}
|
499 |
+
|
500 |
+
public static function refund($transactionId, $amount = null)
|
501 |
+
{
|
502 |
+
return Braintree_Configuration::gateway()->transaction()->refund($transactionId, $amount);
|
503 |
+
}
|
504 |
+
}
|
lib/Braintree/Transaction/AddressDetails.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Creates an instance of AddressDetails as returned from a transaction
|
4 |
+
*
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Transaction
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*
|
10 |
+
* @property-read string $firstName
|
11 |
+
* @property-read string $lastName
|
12 |
+
* @property-read string $company
|
13 |
+
* @property-read string $streetAddress
|
14 |
+
* @property-read string $extendedAddress
|
15 |
+
* @property-read string $locality
|
16 |
+
* @property-read string $region
|
17 |
+
* @property-read string $postalCode
|
18 |
+
* @property-read string $countryName
|
19 |
+
* @uses Braintree_Instance inherits methods
|
20 |
+
*/
|
21 |
+
class Braintree_Transaction_AddressDetails extends Braintree_Instance
|
22 |
+
{
|
23 |
+
protected $_attributes = array();
|
24 |
+
}
|
lib/Braintree/Transaction/ApplePayCardDetails.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Apple Pay card details from a transaction
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Transaction
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* creates an instance of ApplePayCardDetails
|
12 |
+
*
|
13 |
+
*
|
14 |
+
* @package Braintree
|
15 |
+
* @subpackage Transaction
|
16 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
17 |
+
*
|
18 |
+
* @property-read string $cardType
|
19 |
+
* @property-read string $paymentInstrumentName
|
20 |
+
* @property-read string $expirationMonth
|
21 |
+
* @property-read string $expirationYear
|
22 |
+
* @property-read string $cardholderName
|
23 |
+
* @uses Braintree_Instance inherits methods
|
24 |
+
*/
|
25 |
+
class Braintree_Transaction_ApplePayCardDetails extends Braintree_Instance
|
26 |
+
{
|
27 |
+
protected $_attributes = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @ignore
|
31 |
+
*/
|
32 |
+
public function __construct($attributes)
|
33 |
+
{
|
34 |
+
parent::__construct($attributes);
|
35 |
+
}
|
36 |
+
}
|
lib/Braintree/Transaction/CoinbaseDetails.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Coinbase details from a transaction
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Transaction
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* creates an instance of Coinbase
|
12 |
+
*
|
13 |
+
*
|
14 |
+
* @package Braintree
|
15 |
+
* @subpackage Transaction
|
16 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
17 |
+
*
|
18 |
+
* @property-read string $token
|
19 |
+
* @property-read string $userId
|
20 |
+
* @property-read string $userName
|
21 |
+
* @property-read string $userEmail
|
22 |
+
* @property-read string $imageUrl
|
23 |
+
* @uses Braintree_Instance inherits methods
|
24 |
+
*/
|
25 |
+
class Braintree_Transaction_CoinbaseDetails extends Braintree_Instance
|
26 |
+
{
|
27 |
+
protected $_attributes = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @ignore
|
31 |
+
*/
|
32 |
+
public function __construct($attributes)
|
33 |
+
{
|
34 |
+
parent::__construct($attributes);
|
35 |
+
}
|
36 |
+
}
|
lib/Braintree/Transaction/CreditCardDetails.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* CreditCard details from a transaction
|
4 |
+
* creates an instance of CreditCardDetails
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Transaction
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*
|
10 |
+
* @property-read string $bin
|
11 |
+
* @property-read string $cardType
|
12 |
+
* @property-read string $expirationDate
|
13 |
+
* @property-read string $expirationMonth
|
14 |
+
* @property-read string $expirationYear
|
15 |
+
* @property-read string $issuerLocation
|
16 |
+
* @property-read string $last4
|
17 |
+
* @property-read string $maskedNumber
|
18 |
+
* @property-read string $token
|
19 |
+
* @uses Braintree_Instance inherits methods
|
20 |
+
*/
|
21 |
+
class Braintree_Transaction_CreditCardDetails extends Braintree_Instance
|
22 |
+
{
|
23 |
+
protected $_attributes = array();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @ignore
|
27 |
+
*/
|
28 |
+
public function __construct($attributes)
|
29 |
+
{
|
30 |
+
parent::__construct($attributes);
|
31 |
+
$this->_attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear;
|
32 |
+
$this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4;
|
33 |
+
|
34 |
+
}
|
35 |
+
}
|
lib/Braintree/Transaction/CustomerDetails.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Customer details from a transaction
|
4 |
+
* Creates an instance of customer details as returned from a transaction
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Transaction
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*
|
10 |
+
* @property-read string $company
|
11 |
+
* @property-read string $email
|
12 |
+
* @property-read string $fax
|
13 |
+
* @property-read string $firstName
|
14 |
+
* @property-read string $id
|
15 |
+
* @property-read string $lastName
|
16 |
+
* @property-read string $phone
|
17 |
+
* @property-read string $website
|
18 |
+
* @uses Braintree_Instance inherits methods
|
19 |
+
*/
|
20 |
+
class Braintree_Transaction_CustomerDetails extends Braintree_Instance
|
21 |
+
{
|
22 |
+
}
|
lib/Braintree/Transaction/PayPalDetails.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* PayPal details from a transaction
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @subpackage Transaction
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* creates an instance of PayPalDetails
|
12 |
+
*
|
13 |
+
*
|
14 |
+
* @package Braintree
|
15 |
+
* @subpackage Transaction
|
16 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
17 |
+
*
|
18 |
+
* @property-read string $payerEmail
|
19 |
+
* @property-read string $paymentId
|
20 |
+
* @property-read string $authorizationId
|
21 |
+
* @property-read string $token
|
22 |
+
* @property-read string $imageUrl
|
23 |
+
* @uses Braintree_Instance inherits methods
|
24 |
+
*/
|
25 |
+
class Braintree_Transaction_PayPalDetails extends Braintree_Instance
|
26 |
+
{
|
27 |
+
protected $_attributes = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @ignore
|
31 |
+
*/
|
32 |
+
public function __construct($attributes)
|
33 |
+
{
|
34 |
+
parent::__construct($attributes);
|
35 |
+
}
|
36 |
+
}
|
lib/Braintree/Transaction/StatusDetails.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Status details from a transaction
|
4 |
+
* Creates an instance of StatusDetails, as part of a transaction response
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*
|
9 |
+
* @property-read string $amount
|
10 |
+
* @property-read string $status
|
11 |
+
* @property-read string $timestamp
|
12 |
+
* @property-read string $transactionSource
|
13 |
+
* @property-read string $user
|
14 |
+
* @uses Braintree_Instance inherits methods
|
15 |
+
*/
|
16 |
+
class Braintree_Transaction_StatusDetails extends Braintree_Instance
|
17 |
+
{
|
18 |
+
}
|
lib/Braintree/Transaction/SubscriptionDetails.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Customer details from a transaction
|
4 |
+
* Creates an instance of customer details as returned from a transaction
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @subpackage Transaction
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*
|
10 |
+
* @property-read string $billing_period_start_date
|
11 |
+
* @property-read string $billing_period_end_date
|
12 |
+
*/
|
13 |
+
class Braintree_Transaction_SubscriptionDetails extends Braintree_Instance
|
14 |
+
{
|
15 |
+
}
|
lib/Braintree/TransactionGateway.php
ADDED
@@ -0,0 +1,444 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree TransactionGateway processor
|
4 |
+
* Creates and manages transactions
|
5 |
+
*
|
6 |
+
*
|
7 |
+
* <b>== More information ==</b>
|
8 |
+
*
|
9 |
+
* For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api}
|
10 |
+
*
|
11 |
+
* @package Braintree
|
12 |
+
* @category Resources
|
13 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
14 |
+
*/
|
15 |
+
|
16 |
+
final class Braintree_TransactionGateway
|
17 |
+
{
|
18 |
+
private $_gateway;
|
19 |
+
private $_config;
|
20 |
+
private $_http;
|
21 |
+
|
22 |
+
public function __construct($gateway)
|
23 |
+
{
|
24 |
+
$this->_gateway = $gateway;
|
25 |
+
$this->_config = $gateway->config;
|
26 |
+
$this->_http = new Braintree_Http($gateway->config);
|
27 |
+
}
|
28 |
+
|
29 |
+
public function cloneTransaction($transactionId, $attribs)
|
30 |
+
{
|
31 |
+
Braintree_Util::verifyKeys(self::cloneSignature(), $attribs);
|
32 |
+
return $this->_doCreate('/transactions/' . $transactionId . '/clone', array('transactionClone' => $attribs));
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @ignore
|
37 |
+
* @access private
|
38 |
+
* @param array $attribs
|
39 |
+
* @return object
|
40 |
+
*/
|
41 |
+
private function create($attribs)
|
42 |
+
{
|
43 |
+
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
|
44 |
+
return $this->_doCreate('/transactions', array('transaction' => $attribs));
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
*
|
49 |
+
* @ignore
|
50 |
+
* @access private
|
51 |
+
* @param array $attribs
|
52 |
+
* @return object
|
53 |
+
* @throws Braintree_Exception_ValidationError
|
54 |
+
*/
|
55 |
+
private function createNoValidate($attribs)
|
56 |
+
{
|
57 |
+
$result = $this->create($attribs);
|
58 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
59 |
+
}
|
60 |
+
/**
|
61 |
+
*
|
62 |
+
* @access public
|
63 |
+
* @param array $attribs
|
64 |
+
* @return object
|
65 |
+
*/
|
66 |
+
public function createFromTransparentRedirect($queryString)
|
67 |
+
{
|
68 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
|
69 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
70 |
+
$queryString
|
71 |
+
);
|
72 |
+
return $this->_doCreate(
|
73 |
+
'/transactions/all/confirm_transparent_redirect_request',
|
74 |
+
array('id' => $params['id'])
|
75 |
+
);
|
76 |
+
}
|
77 |
+
/**
|
78 |
+
*
|
79 |
+
* @access public
|
80 |
+
* @param none
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function createTransactionUrl()
|
84 |
+
{
|
85 |
+
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
|
86 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() .
|
87 |
+
'/transactions/all/create_via_transparent_redirect_request';
|
88 |
+
}
|
89 |
+
|
90 |
+
public static function cloneSignature()
|
91 |
+
{
|
92 |
+
return array('amount', 'channel', array('options' => array('submitForSettlement')));
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* creates a full array signature of a valid gateway request
|
97 |
+
* @return array gateway request signature format
|
98 |
+
*/
|
99 |
+
public static function createSignature()
|
100 |
+
{
|
101 |
+
return array(
|
102 |
+
'amount',
|
103 |
+
'billingAddressId',
|
104 |
+
'channel',
|
105 |
+
'customerId',
|
106 |
+
'deviceData',
|
107 |
+
'deviceSessionId',
|
108 |
+
'fraudMerchantId',
|
109 |
+
'merchantAccountId',
|
110 |
+
'orderId',
|
111 |
+
'paymentMethodNonce',
|
112 |
+
'paymentMethodToken',
|
113 |
+
'purchaseOrderNumber',
|
114 |
+
'recurring',
|
115 |
+
'serviceFeeAmount',
|
116 |
+
'shippingAddressId',
|
117 |
+
'taxAmount',
|
118 |
+
'taxExempt',
|
119 |
+
'threeDSecureToken',
|
120 |
+
'type',
|
121 |
+
'venmoSdkPaymentMethodCode',
|
122 |
+
array('creditCard' =>
|
123 |
+
array('token', 'cardholderName', 'cvv', 'expirationDate', 'expirationMonth', 'expirationYear', 'number'),
|
124 |
+
),
|
125 |
+
array('customer' =>
|
126 |
+
array(
|
127 |
+
'id', 'company', 'email', 'fax', 'firstName',
|
128 |
+
'lastName', 'phone', 'website'),
|
129 |
+
),
|
130 |
+
array('billing' =>
|
131 |
+
array(
|
132 |
+
'firstName', 'lastName', 'company', 'countryName',
|
133 |
+
'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
|
134 |
+
'extendedAddress', 'locality', 'postalCode', 'region',
|
135 |
+
'streetAddress'),
|
136 |
+
),
|
137 |
+
array('shipping' =>
|
138 |
+
array(
|
139 |
+
'firstName', 'lastName', 'company', 'countryName',
|
140 |
+
'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
|
141 |
+
'extendedAddress', 'locality', 'postalCode', 'region',
|
142 |
+
'streetAddress'),
|
143 |
+
),
|
144 |
+
array('options' =>
|
145 |
+
array(
|
146 |
+
'holdInEscrow',
|
147 |
+
'storeInVault',
|
148 |
+
'storeInVaultOnSuccess',
|
149 |
+
'submitForSettlement',
|
150 |
+
'addBillingAddressToPaymentMethod',
|
151 |
+
'venmoSdkSession',
|
152 |
+
'storeShippingAddressInVault',
|
153 |
+
'payeeEmail',
|
154 |
+
array('three_d_secure' =>
|
155 |
+
array('required')
|
156 |
+
),
|
157 |
+
array('paypal' =>
|
158 |
+
array(
|
159 |
+
'payeeEmail',
|
160 |
+
'customField'
|
161 |
+
)
|
162 |
+
)
|
163 |
+
),
|
164 |
+
),
|
165 |
+
array('customFields' => array('_anyKey_')
|
166 |
+
),
|
167 |
+
array('descriptor' => array('name', 'phone', 'url')),
|
168 |
+
array('paypalAccount' => array('payeeEmail')),
|
169 |
+
array('industry' =>
|
170 |
+
array('industryType',
|
171 |
+
array('data' =>
|
172 |
+
array(
|
173 |
+
'folioNumber',
|
174 |
+
'checkInDate',
|
175 |
+
'checkOutDate',
|
176 |
+
'travelPackage',
|
177 |
+
'departureDate',
|
178 |
+
'lodgingCheckInDate',
|
179 |
+
'lodgingCheckOutDate',
|
180 |
+
'lodgingName',
|
181 |
+
'roomRate'
|
182 |
+
)
|
183 |
+
)
|
184 |
+
)
|
185 |
+
)
|
186 |
+
);
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
*
|
191 |
+
* @access public
|
192 |
+
* @param array $attribs
|
193 |
+
* @return object
|
194 |
+
*/
|
195 |
+
public function credit($attribs)
|
196 |
+
{
|
197 |
+
return $this->create(array_merge($attribs, array('type' => Braintree_Transaction::CREDIT)));
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
*
|
202 |
+
* @access public
|
203 |
+
* @param array $attribs
|
204 |
+
* @return object
|
205 |
+
* @throws Braintree_Exception_ValidationError
|
206 |
+
*/
|
207 |
+
public function creditNoValidate($attribs)
|
208 |
+
{
|
209 |
+
$result = $this->credit($attribs);
|
210 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
211 |
+
}
|
212 |
+
|
213 |
+
|
214 |
+
/**
|
215 |
+
* @access public
|
216 |
+
*
|
217 |
+
*/
|
218 |
+
public function find($id)
|
219 |
+
{
|
220 |
+
$this->_validateId($id);
|
221 |
+
try {
|
222 |
+
$path = $this->_config->merchantPath() . '/transactions/' . $id;
|
223 |
+
$response = $this->_http->get($path);
|
224 |
+
return Braintree_Transaction::factory($response['transaction']);
|
225 |
+
} catch (Braintree_Exception_NotFound $e) {
|
226 |
+
throw new Braintree_Exception_NotFound(
|
227 |
+
'transaction with id ' . $id . ' not found'
|
228 |
+
);
|
229 |
+
}
|
230 |
+
|
231 |
+
}
|
232 |
+
/**
|
233 |
+
* new sale
|
234 |
+
* @param array $attribs
|
235 |
+
* @return array
|
236 |
+
*/
|
237 |
+
public function sale($attribs)
|
238 |
+
{
|
239 |
+
return $this->create(array_merge(array('type' => Braintree_Transaction::SALE), $attribs));
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* roughly equivalent to the ruby bang method
|
244 |
+
* @access public
|
245 |
+
* @param array $attribs
|
246 |
+
* @return array
|
247 |
+
* @throws Braintree_Exception_ValidationsFailed
|
248 |
+
*/
|
249 |
+
public function saleNoValidate($attribs)
|
250 |
+
{
|
251 |
+
$result = $this->sale($attribs);
|
252 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Returns a ResourceCollection of transactions matching the search query.
|
257 |
+
*
|
258 |
+
* If <b>query</b> is a string, the search will be a basic search.
|
259 |
+
* If <b>query</b> is a hash, the search will be an advanced search.
|
260 |
+
* For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/transaction-api#searching http://www.braintreepaymentsolutions.com/gateway/transaction-api}
|
261 |
+
*
|
262 |
+
* @param mixed $query search query
|
263 |
+
* @param array $options options such as page number
|
264 |
+
* @return object Braintree_ResourceCollection
|
265 |
+
* @throws InvalidArgumentException
|
266 |
+
*/
|
267 |
+
public function search($query)
|
268 |
+
{
|
269 |
+
$criteria = array();
|
270 |
+
foreach ($query as $term) {
|
271 |
+
$criteria[$term->name] = $term->toparam();
|
272 |
+
}
|
273 |
+
|
274 |
+
$path = $this->_config->merchantPath() . '/transactions/advanced_search_ids';
|
275 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
276 |
+
if (array_key_exists('searchResults', $response)) {
|
277 |
+
$pager = array(
|
278 |
+
'object' => $this,
|
279 |
+
'method' => 'fetch',
|
280 |
+
'methodArgs' => array($query)
|
281 |
+
);
|
282 |
+
|
283 |
+
return new Braintree_ResourceCollection($response, $pager);
|
284 |
+
} else {
|
285 |
+
throw new Braintree_Exception_DownForMaintenance();
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
public function fetch($query, $ids)
|
290 |
+
{
|
291 |
+
$criteria = array();
|
292 |
+
foreach ($query as $term) {
|
293 |
+
$criteria[$term->name] = $term->toparam();
|
294 |
+
}
|
295 |
+
$criteria["ids"] = Braintree_TransactionSearch::ids()->in($ids)->toparam();
|
296 |
+
$path = $this->_config->merchantPath() . '/transactions/advanced_search';
|
297 |
+
$response = $this->_http->post($path, array('search' => $criteria));
|
298 |
+
|
299 |
+
return Braintree_Util::extractattributeasarray(
|
300 |
+
$response['creditCardTransactions'],
|
301 |
+
'transaction'
|
302 |
+
);
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* void a transaction by id
|
307 |
+
*
|
308 |
+
* @param string $id transaction id
|
309 |
+
* @return object Braintree_Result_Successful|Braintree_Result_Error
|
310 |
+
*/
|
311 |
+
public function void($transactionId)
|
312 |
+
{
|
313 |
+
$this->_validateId($transactionId);
|
314 |
+
|
315 |
+
$path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/void';
|
316 |
+
$response = $this->_http->put($path);
|
317 |
+
return $this->_verifyGatewayResponse($response);
|
318 |
+
}
|
319 |
+
/**
|
320 |
+
*
|
321 |
+
*/
|
322 |
+
public function voidNoValidate($transactionId)
|
323 |
+
{
|
324 |
+
$result = $this->void($transactionId);
|
325 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
326 |
+
}
|
327 |
+
|
328 |
+
public function submitForSettlement($transactionId, $amount = null)
|
329 |
+
{
|
330 |
+
$this->_validateId($transactionId);
|
331 |
+
|
332 |
+
$path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_settlement';
|
333 |
+
$response = $this->_http->put($path, array('transaction' => array('amount' => $amount)));
|
334 |
+
return $this->_verifyGatewayResponse($response);
|
335 |
+
}
|
336 |
+
|
337 |
+
public function submitForSettlementNoValidate($transactionId, $amount = null)
|
338 |
+
{
|
339 |
+
$result = $this->submitForSettlement($transactionId, $amount);
|
340 |
+
return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
|
341 |
+
}
|
342 |
+
|
343 |
+
public function holdInEscrow($transactionId)
|
344 |
+
{
|
345 |
+
$this->_validateId($transactionId);
|
346 |
+
|
347 |
+
$path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/hold_in_escrow';
|
348 |
+
$response = $this->_http->put($path, array());
|
349 |
+
return $this->_verifyGatewayResponse($response);
|
350 |
+
}
|
351 |
+
|
352 |
+
public function releaseFromEscrow($transactionId)
|
353 |
+
{
|
354 |
+
$this->_validateId($transactionId);
|
355 |
+
|
356 |
+
$path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/release_from_escrow';
|
357 |
+
$response = $this->_http->put($path, array());
|
358 |
+
return $this->_verifyGatewayResponse($response);
|
359 |
+
}
|
360 |
+
|
361 |
+
public function cancelRelease($transactionId)
|
362 |
+
{
|
363 |
+
$this->_validateId($transactionId);
|
364 |
+
|
365 |
+
$path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/cancel_release';
|
366 |
+
$response = $this->_http->put($path, array());
|
367 |
+
return $this->_verifyGatewayResponse($response);
|
368 |
+
}
|
369 |
+
|
370 |
+
public function refund($transactionId, $amount = null)
|
371 |
+
{
|
372 |
+
self::_validateId($transactionId);
|
373 |
+
|
374 |
+
$params = array('transaction' => array('amount' => $amount));
|
375 |
+
$path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/refund';
|
376 |
+
$response = $this->_http->post($path, $params);
|
377 |
+
return $this->_verifyGatewayResponse($response);
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* sends the create request to the gateway
|
382 |
+
*
|
383 |
+
* @ignore
|
384 |
+
* @param var $subPath
|
385 |
+
* @param array $params
|
386 |
+
* @return mixed
|
387 |
+
*/
|
388 |
+
public function _doCreate($subPath, $params)
|
389 |
+
{
|
390 |
+
$fullPath = $this->_config->merchantPath() . $subPath;
|
391 |
+
$response = $this->_http->post($fullPath, $params);
|
392 |
+
|
393 |
+
return $this->_verifyGatewayResponse($response);
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* verifies that a valid transaction id is being used
|
398 |
+
* @ignore
|
399 |
+
* @param string transaction id
|
400 |
+
* @throws InvalidArgumentException
|
401 |
+
*/
|
402 |
+
private function _validateId($id = null) {
|
403 |
+
if (empty($id)) {
|
404 |
+
throw new InvalidArgumentException(
|
405 |
+
'expected transaction id to be set'
|
406 |
+
);
|
407 |
+
}
|
408 |
+
if (!preg_match('/^[0-9a-z]+$/', $id)) {
|
409 |
+
throw new InvalidArgumentException(
|
410 |
+
$id . ' is an invalid transaction id.'
|
411 |
+
);
|
412 |
+
}
|
413 |
+
}
|
414 |
+
|
415 |
+
|
416 |
+
/**
|
417 |
+
* generic method for validating incoming gateway responses
|
418 |
+
*
|
419 |
+
* creates a new Braintree_Transaction object and encapsulates
|
420 |
+
* it inside a Braintree_Result_Successful object, or
|
421 |
+
* encapsulates a Braintree_Errors object inside a Result_Error
|
422 |
+
* alternatively, throws an Unexpected exception if the response is invalid.
|
423 |
+
*
|
424 |
+
* @ignore
|
425 |
+
* @param array $response gateway response values
|
426 |
+
* @return object Result_Successful or Result_Error
|
427 |
+
* @throws Braintree_Exception_Unexpected
|
428 |
+
*/
|
429 |
+
private function _verifyGatewayResponse($response)
|
430 |
+
{
|
431 |
+
if (isset($response['transaction'])) {
|
432 |
+
// return a populated instance of Braintree_Transaction
|
433 |
+
return new Braintree_Result_Successful(
|
434 |
+
Braintree_Transaction::factory($response['transaction'])
|
435 |
+
);
|
436 |
+
} else if (isset($response['apiErrorResponse'])) {
|
437 |
+
return new Braintree_Result_Error($response['apiErrorResponse']);
|
438 |
+
} else {
|
439 |
+
throw new Braintree_Exception_Unexpected(
|
440 |
+
"Expected transaction or apiErrorResponse"
|
441 |
+
);
|
442 |
+
}
|
443 |
+
}
|
444 |
+
}
|
lib/Braintree/TransactionSearch.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_TransactionSearch
|
3 |
+
{
|
4 |
+
static function billingCompany() { return new Braintree_TextNode('billing_company'); }
|
5 |
+
static function billingCountryName() { return new Braintree_TextNode('billing_country_name'); }
|
6 |
+
static function billingExtendedAddress() { return new Braintree_TextNode('billing_extended_address'); }
|
7 |
+
static function billingFirstName() { return new Braintree_TextNode('billing_first_name'); }
|
8 |
+
static function billingLastName() { return new Braintree_TextNode('billing_last_name'); }
|
9 |
+
static function billingLocality() { return new Braintree_TextNode('billing_locality'); }
|
10 |
+
static function billingPostalCode() { return new Braintree_TextNode('billing_postal_code'); }
|
11 |
+
static function billingRegion() { return new Braintree_TextNode('billing_region'); }
|
12 |
+
static function billingStreetAddress() { return new Braintree_TextNode('billing_street_address'); }
|
13 |
+
static function creditCardCardholderName() { return new Braintree_TextNode('credit_card_cardholderName'); }
|
14 |
+
static function customerCompany() { return new Braintree_TextNode('customer_company'); }
|
15 |
+
static function customerEmail() { return new Braintree_TextNode('customer_email'); }
|
16 |
+
static function customerFax() { return new Braintree_TextNode('customer_fax'); }
|
17 |
+
static function customerFirstName() { return new Braintree_TextNode('customer_first_name'); }
|
18 |
+
static function customerId() { return new Braintree_TextNode('customer_id'); }
|
19 |
+
static function customerLastName() { return new Braintree_TextNode('customer_last_name'); }
|
20 |
+
static function customerPhone() { return new Braintree_TextNode('customer_phone'); }
|
21 |
+
static function customerWebsite() { return new Braintree_TextNode('customer_website'); }
|
22 |
+
static function id() { return new Braintree_TextNode('id'); }
|
23 |
+
static function ids() { return new Braintree_MultipleValueNode('ids'); }
|
24 |
+
static function orderId() { return new Braintree_TextNode('order_id'); }
|
25 |
+
static function paymentMethodToken() { return new Braintree_TextNode('payment_method_token'); }
|
26 |
+
static function processorAuthorizationCode() { return new Braintree_TextNode('processor_authorization_code'); }
|
27 |
+
static function settlementBatchId() { return new Braintree_TextNode('settlement_batch_id'); }
|
28 |
+
static function shippingCompany() { return new Braintree_TextNode('shipping_company'); }
|
29 |
+
static function shippingCountryName() { return new Braintree_TextNode('shipping_country_name'); }
|
30 |
+
static function shippingExtendedAddress() { return new Braintree_TextNode('shipping_extended_address'); }
|
31 |
+
static function shippingFirstName() { return new Braintree_TextNode('shipping_first_name'); }
|
32 |
+
static function shippingLastName() { return new Braintree_TextNode('shipping_last_name'); }
|
33 |
+
static function shippingLocality() { return new Braintree_TextNode('shipping_locality'); }
|
34 |
+
static function shippingPostalCode() { return new Braintree_TextNode('shipping_postal_code'); }
|
35 |
+
static function shippingRegion() { return new Braintree_TextNode('shipping_region'); }
|
36 |
+
static function shippingStreetAddress() { return new Braintree_TextNode('shipping_street_address'); }
|
37 |
+
static function paypalPaymentId() { return new Braintree_TextNode('paypal_payment_id'); }
|
38 |
+
static function paypalAuthorizationId() { return new Braintree_TextNode('paypal_authorization_id'); }
|
39 |
+
static function paypalPayerEmail() { return new Braintree_TextNode('paypal_payer_email'); }
|
40 |
+
|
41 |
+
static function creditCardExpirationDate() { return new Braintree_EqualityNode('credit_card_expiration_date'); }
|
42 |
+
|
43 |
+
static function creditCardNumber() { return new Braintree_PartialMatchNode('credit_card_number'); }
|
44 |
+
|
45 |
+
static function refund() { return new Braintree_KeyValueNode("refund"); }
|
46 |
+
|
47 |
+
static function amount() { return new Braintree_RangeNode("amount"); }
|
48 |
+
static function authorizedAt() { return new Braintree_RangeNode("authorizedAt"); }
|
49 |
+
static function authorizationExpiredAt() { return new Braintree_RangeNode("authorizationExpiredAt"); }
|
50 |
+
static function createdAt() { return new Braintree_RangeNode("createdAt"); }
|
51 |
+
static function failedAt() { return new Braintree_RangeNode("failedAt"); }
|
52 |
+
static function gatewayRejectedAt() { return new Braintree_RangeNode("gatewayRejectedAt"); }
|
53 |
+
static function processorDeclinedAt() { return new Braintree_RangeNode("processorDeclinedAt"); }
|
54 |
+
static function settledAt() { return new Braintree_RangeNode("settledAt"); }
|
55 |
+
static function submittedForSettlementAt() { return new Braintree_RangeNode("submittedForSettlementAt"); }
|
56 |
+
static function voidedAt() { return new Braintree_RangeNode("voidedAt"); }
|
57 |
+
static function disbursementDate() { return new Braintree_RangeNode("disbursementDate"); }
|
58 |
+
static function disputeDate() { return new Braintree_RangeNode("disputeDate"); }
|
59 |
+
|
60 |
+
static function merchantAccountId() { return new Braintree_MultipleValueNode("merchant_account_id"); }
|
61 |
+
|
62 |
+
static function createdUsing()
|
63 |
+
{
|
64 |
+
return new Braintree_MultipleValueNode("created_using", array(
|
65 |
+
Braintree_Transaction::FULL_INFORMATION,
|
66 |
+
Braintree_Transaction::TOKEN
|
67 |
+
));
|
68 |
+
}
|
69 |
+
|
70 |
+
static function creditCardCardType()
|
71 |
+
{
|
72 |
+
return new Braintree_MultipleValueNode("credit_card_card_type", array(
|
73 |
+
Braintree_CreditCard::AMEX,
|
74 |
+
Braintree_CreditCard::CARTE_BLANCHE,
|
75 |
+
Braintree_CreditCard::CHINA_UNION_PAY,
|
76 |
+
Braintree_CreditCard::DINERS_CLUB_INTERNATIONAL,
|
77 |
+
Braintree_CreditCard::DISCOVER,
|
78 |
+
Braintree_CreditCard::JCB,
|
79 |
+
Braintree_CreditCard::LASER,
|
80 |
+
Braintree_CreditCard::MAESTRO,
|
81 |
+
Braintree_CreditCard::MASTER_CARD,
|
82 |
+
Braintree_CreditCard::SOLO,
|
83 |
+
Braintree_CreditCard::SWITCH_TYPE,
|
84 |
+
Braintree_CreditCard::VISA,
|
85 |
+
Braintree_CreditCard::UNKNOWN
|
86 |
+
));
|
87 |
+
}
|
88 |
+
|
89 |
+
static function creditCardCustomerLocation()
|
90 |
+
{
|
91 |
+
return new Braintree_MultipleValueNode("credit_card_customer_location", array(
|
92 |
+
Braintree_CreditCard::INTERNATIONAL,
|
93 |
+
Braintree_CreditCard::US
|
94 |
+
));
|
95 |
+
}
|
96 |
+
|
97 |
+
static function source()
|
98 |
+
{
|
99 |
+
return new Braintree_MultipleValueNode("source", array(
|
100 |
+
Braintree_Transaction::API,
|
101 |
+
Braintree_Transaction::CONTROL_PANEL,
|
102 |
+
Braintree_Transaction::RECURRING,
|
103 |
+
));
|
104 |
+
}
|
105 |
+
|
106 |
+
static function status()
|
107 |
+
{
|
108 |
+
return new Braintree_MultipleValueNode("status", array(
|
109 |
+
Braintree_Transaction::AUTHORIZATION_EXPIRED,
|
110 |
+
Braintree_Transaction::AUTHORIZING,
|
111 |
+
Braintree_Transaction::AUTHORIZED,
|
112 |
+
Braintree_Transaction::GATEWAY_REJECTED,
|
113 |
+
Braintree_Transaction::FAILED,
|
114 |
+
Braintree_Transaction::PROCESSOR_DECLINED,
|
115 |
+
Braintree_Transaction::SETTLED,
|
116 |
+
Braintree_Transaction::SETTLING,
|
117 |
+
Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT,
|
118 |
+
Braintree_Transaction::VOIDED,
|
119 |
+
Braintree_Transaction::SETTLEMENT_DECLINED,
|
120 |
+
Braintree_Transaction::SETTLEMENT_PENDING
|
121 |
+
));
|
122 |
+
}
|
123 |
+
|
124 |
+
static function type()
|
125 |
+
{
|
126 |
+
return new Braintree_MultipleValueNode("type", array(
|
127 |
+
Braintree_Transaction::SALE,
|
128 |
+
Braintree_Transaction::CREDIT
|
129 |
+
));
|
130 |
+
}
|
131 |
+
}
|
lib/Braintree/TransparentRedirect.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Braintree Transparent Redirect module
|
6 |
+
* Static class providing methods to build Transparent Redirect urls
|
7 |
+
*
|
8 |
+
* The TransparentRedirect module provides methods to build the tr_data param
|
9 |
+
* that must be submitted when using the transparent redirect API.
|
10 |
+
* For more information
|
11 |
+
* about transparent redirect, see (TODO).
|
12 |
+
*
|
13 |
+
* You must provide a redirectUrl to which the gateway will redirect the
|
14 |
+
* user the action is complete.
|
15 |
+
*
|
16 |
+
* <code>
|
17 |
+
* $trData = Braintree_TransparentRedirect::createCustomerData(array(
|
18 |
+
* 'redirectUrl => 'http://example.com/redirect_back_to_merchant_site',
|
19 |
+
* ));
|
20 |
+
* </code>
|
21 |
+
*
|
22 |
+
* In addition to the redirectUrl, any data that needs to be protected
|
23 |
+
* from user tampering should be included in the trData.
|
24 |
+
* For example, to prevent the user from tampering with the transaction
|
25 |
+
* amount, include the amount in the trData.
|
26 |
+
*
|
27 |
+
* <code>
|
28 |
+
* $trData = Braintree_TransparentRedirect::transactionData(array(
|
29 |
+
* 'redirectUrl' => 'http://example.com/complete_transaction',
|
30 |
+
* 'transaction' => array('amount' => '100.00'),
|
31 |
+
* ));
|
32 |
+
*
|
33 |
+
* </code>
|
34 |
+
*
|
35 |
+
* @package Braintree
|
36 |
+
* @category Resources
|
37 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
38 |
+
*/
|
39 |
+
class Braintree_TransparentRedirect
|
40 |
+
{
|
41 |
+
// Request Kinds
|
42 |
+
const CREATE_TRANSACTION = 'create_transaction';
|
43 |
+
const CREATE_PAYMENT_METHOD = 'create_payment_method';
|
44 |
+
const UPDATE_PAYMENT_METHOD = 'update_payment_method';
|
45 |
+
const CREATE_CUSTOMER = 'create_customer';
|
46 |
+
const UPDATE_CUSTOMER = 'update_customer';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @ignore
|
50 |
+
* don't permit an explicit call of the constructor!
|
51 |
+
* (like $t = new Braintree_TransparentRedirect())
|
52 |
+
*/
|
53 |
+
protected function __construct()
|
54 |
+
{
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
// static methods redirecting to gateway
|
60 |
+
|
61 |
+
public static function confirm($queryString)
|
62 |
+
{
|
63 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->confirm($queryString);
|
64 |
+
}
|
65 |
+
|
66 |
+
public static function createCreditCardData($params)
|
67 |
+
{
|
68 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->createCreditCardData($params);
|
69 |
+
}
|
70 |
+
|
71 |
+
public static function createCustomerData($params)
|
72 |
+
{
|
73 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->createCustomerData($params);
|
74 |
+
}
|
75 |
+
|
76 |
+
public static function url()
|
77 |
+
{
|
78 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->url();
|
79 |
+
}
|
80 |
+
|
81 |
+
public static function transactionData($params)
|
82 |
+
{
|
83 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->transactionData($params);
|
84 |
+
}
|
85 |
+
|
86 |
+
public static function updateCreditCardData($params)
|
87 |
+
{
|
88 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->updateCreditCardData($params);
|
89 |
+
}
|
90 |
+
|
91 |
+
public static function updateCustomerData($params)
|
92 |
+
{
|
93 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->updateCustomerData($params);
|
94 |
+
}
|
95 |
+
|
96 |
+
public static function parseAndValidateQueryString($queryString)
|
97 |
+
{
|
98 |
+
return Braintree_Configuration::gateway()->transparentRedirect()->parseAndValidateQueryString($queryString);
|
99 |
+
}
|
100 |
+
}
|
lib/Braintree/TransparentRedirectGateway.php
ADDED
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Transparent Redirect Gateway module
|
4 |
+
* Static class providing methods to build Transparent Redirect urls
|
5 |
+
*
|
6 |
+
* @package Braintree
|
7 |
+
* @category Resources
|
8 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
9 |
+
*/
|
10 |
+
class Braintree_TransparentRedirectGateway
|
11 |
+
{
|
12 |
+
private $_gateway;
|
13 |
+
private $_config;
|
14 |
+
|
15 |
+
public function __construct($gateway)
|
16 |
+
{
|
17 |
+
$this->_gateway = $gateway;
|
18 |
+
$this->_config = $gateway->config;
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
*
|
23 |
+
* @ignore
|
24 |
+
*/
|
25 |
+
private static $_transparentRedirectKeys = 'redirectUrl';
|
26 |
+
private static $_createCustomerSignature;
|
27 |
+
private static $_updateCustomerSignature;
|
28 |
+
private static $_transactionSignature;
|
29 |
+
private static $_createCreditCardSignature;
|
30 |
+
private static $_updateCreditCardSignature;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* create signatures for different call types
|
34 |
+
* @ignore
|
35 |
+
*/
|
36 |
+
public static function init()
|
37 |
+
{
|
38 |
+
|
39 |
+
self::$_createCustomerSignature = array(
|
40 |
+
self::$_transparentRedirectKeys,
|
41 |
+
array('customer' => Braintree_CustomerGateway::createSignature()),
|
42 |
+
);
|
43 |
+
self::$_updateCustomerSignature = array(
|
44 |
+
self::$_transparentRedirectKeys,
|
45 |
+
'customerId',
|
46 |
+
array('customer' => Braintree_CustomerGateway::updateSignature()),
|
47 |
+
);
|
48 |
+
self::$_transactionSignature = array(
|
49 |
+
self::$_transparentRedirectKeys,
|
50 |
+
array('transaction' => Braintree_TransactionGateway::createSignature()),
|
51 |
+
);
|
52 |
+
self::$_createCreditCardSignature = array(
|
53 |
+
self::$_transparentRedirectKeys,
|
54 |
+
array('creditCard' => Braintree_CreditCardGateway::createSignature()),
|
55 |
+
);
|
56 |
+
self::$_updateCreditCardSignature = array(
|
57 |
+
self::$_transparentRedirectKeys,
|
58 |
+
'paymentMethodToken',
|
59 |
+
array('creditCard' => Braintree_CreditCardGateway::updateSignature()),
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
public function confirm($queryString)
|
64 |
+
{
|
65 |
+
$params = Braintree_TransparentRedirect::parseAndValidateQueryString(
|
66 |
+
$queryString
|
67 |
+
);
|
68 |
+
$confirmationKlasses = array(
|
69 |
+
Braintree_TransparentRedirect::CREATE_TRANSACTION => 'Braintree_TransactionGateway',
|
70 |
+
Braintree_TransparentRedirect::CREATE_CUSTOMER => 'Braintree_CustomerGateway',
|
71 |
+
Braintree_TransparentRedirect::UPDATE_CUSTOMER => 'Braintree_CustomerGateway',
|
72 |
+
Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD => 'Braintree_CreditCardGateway',
|
73 |
+
Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD => 'Braintree_CreditCardGateway'
|
74 |
+
);
|
75 |
+
$confirmationGateway = new $confirmationKlasses[$params["kind"]]($this->_gateway);
|
76 |
+
return $confirmationGateway->_doCreate('/transparent_redirect_requests/' . $params['id'] . '/confirm', array());
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* returns the trData string for creating a credit card,
|
81 |
+
* @param array $params
|
82 |
+
* @return string
|
83 |
+
*/
|
84 |
+
public function createCreditCardData($params)
|
85 |
+
{
|
86 |
+
Braintree_Util::verifyKeys(
|
87 |
+
self::$_createCreditCardSignature,
|
88 |
+
$params
|
89 |
+
);
|
90 |
+
$params["kind"] = Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD;
|
91 |
+
return $this->_data($params);
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* returns the trData string for creating a customer.
|
96 |
+
* @param array $params
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
public function createCustomerData($params)
|
100 |
+
{
|
101 |
+
Braintree_Util::verifyKeys(
|
102 |
+
self::$_createCustomerSignature,
|
103 |
+
$params
|
104 |
+
);
|
105 |
+
$params["kind"] = Braintree_TransparentRedirect::CREATE_CUSTOMER;
|
106 |
+
return $this->_data($params);
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
public function url()
|
111 |
+
{
|
112 |
+
return $this->_config->baseUrl() . $this->_config->merchantPath() . "/transparent_redirect_requests";
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* returns the trData string for creating a transaction
|
117 |
+
* @param array $params
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public function transactionData($params)
|
121 |
+
{
|
122 |
+
Braintree_Util::verifyKeys(
|
123 |
+
self::$_transactionSignature,
|
124 |
+
$params
|
125 |
+
);
|
126 |
+
$params["kind"] = Braintree_TransparentRedirect::CREATE_TRANSACTION;
|
127 |
+
$transactionType = isset($params['transaction']['type']) ?
|
128 |
+
$params['transaction']['type'] :
|
129 |
+
null;
|
130 |
+
if ($transactionType != Braintree_Transaction::SALE && $transactionType != Braintree_Transaction::CREDIT) {
|
131 |
+
throw new InvalidArgumentException(
|
132 |
+
'expected transaction[type] of sale or credit, was: ' .
|
133 |
+
$transactionType
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
return $this->_data($params);
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Returns the trData string for updating a credit card.
|
142 |
+
*
|
143 |
+
* The paymentMethodToken of the credit card to update is required.
|
144 |
+
*
|
145 |
+
* <code>
|
146 |
+
* $trData = Braintree_TransparentRedirect::updateCreditCardData(array(
|
147 |
+
* 'redirectUrl' => 'http://example.com/redirect_here',
|
148 |
+
* 'paymentMethodToken' => 'token123',
|
149 |
+
* ));
|
150 |
+
* </code>
|
151 |
+
*
|
152 |
+
* @param array $params
|
153 |
+
* @return string
|
154 |
+
*/
|
155 |
+
public function updateCreditCardData($params)
|
156 |
+
{
|
157 |
+
Braintree_Util::verifyKeys(
|
158 |
+
self::$_updateCreditCardSignature,
|
159 |
+
$params
|
160 |
+
);
|
161 |
+
if (!isset($params['paymentMethodToken'])) {
|
162 |
+
throw new InvalidArgumentException(
|
163 |
+
'expected params to contain paymentMethodToken.'
|
164 |
+
);
|
165 |
+
}
|
166 |
+
$params["kind"] = Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD;
|
167 |
+
return $this->_data($params);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Returns the trData string for updating a customer.
|
172 |
+
*
|
173 |
+
* The customerId of the customer to update is required.
|
174 |
+
*
|
175 |
+
* <code>
|
176 |
+
* $trData = Braintree_TransparentRedirect::updateCustomerData(array(
|
177 |
+
* 'redirectUrl' => 'http://example.com/redirect_here',
|
178 |
+
* 'customerId' => 'customer123',
|
179 |
+
* ));
|
180 |
+
* </code>
|
181 |
+
*
|
182 |
+
* @param array $params
|
183 |
+
* @return string
|
184 |
+
*/
|
185 |
+
public function updateCustomerData($params)
|
186 |
+
{
|
187 |
+
Braintree_Util::verifyKeys(
|
188 |
+
self::$_updateCustomerSignature,
|
189 |
+
$params
|
190 |
+
);
|
191 |
+
if (!isset($params['customerId'])) {
|
192 |
+
throw new InvalidArgumentException(
|
193 |
+
'expected params to contain customerId of customer to update'
|
194 |
+
);
|
195 |
+
}
|
196 |
+
$params["kind"] = Braintree_TransparentRedirect::UPDATE_CUSTOMER;
|
197 |
+
return $this->_data($params);
|
198 |
+
}
|
199 |
+
|
200 |
+
public function parseAndValidateQueryString($queryString)
|
201 |
+
{
|
202 |
+
// parse the params into an array
|
203 |
+
parse_str($queryString, $params);
|
204 |
+
// remove the hash
|
205 |
+
$queryStringWithoutHash = null;
|
206 |
+
if(preg_match('/^(.*)&hash=[a-f0-9]+$/', $queryString, $match)) {
|
207 |
+
$queryStringWithoutHash = $match[1];
|
208 |
+
}
|
209 |
+
|
210 |
+
if($params['http_status'] != '200') {
|
211 |
+
$message = null;
|
212 |
+
if(array_key_exists('bt_message', $params)) {
|
213 |
+
$message = $params['bt_message'];
|
214 |
+
}
|
215 |
+
Braintree_Util::throwStatusCodeException($params['http_status'], $message);
|
216 |
+
}
|
217 |
+
|
218 |
+
// recreate the hash and compare it
|
219 |
+
if($this->_hash($queryStringWithoutHash) == $params['hash']) {
|
220 |
+
return $params;
|
221 |
+
} else {
|
222 |
+
throw new Braintree_Exception_ForgedQueryString();
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
*
|
229 |
+
* @ignore
|
230 |
+
*/
|
231 |
+
private function _data($params)
|
232 |
+
{
|
233 |
+
if (!isset($params['redirectUrl'])) {
|
234 |
+
throw new InvalidArgumentException(
|
235 |
+
'expected params to contain redirectUrl'
|
236 |
+
);
|
237 |
+
}
|
238 |
+
$params = $this->_underscoreKeys($params);
|
239 |
+
$now = new DateTime('now', new DateTimeZone('UTC'));
|
240 |
+
$trDataParams = array_merge($params,
|
241 |
+
array(
|
242 |
+
'api_version' => Braintree_Configuration::API_VERSION,
|
243 |
+
'public_key' => $this->_config->publicKey(),
|
244 |
+
'time' => $now->format('YmdHis'),
|
245 |
+
)
|
246 |
+
);
|
247 |
+
ksort($trDataParams);
|
248 |
+
$urlEncodedData = http_build_query($trDataParams, null, "&");
|
249 |
+
$signatureService = new Braintree_SignatureService(
|
250 |
+
$this->_config->privateKey(),
|
251 |
+
"Braintree_Digest::hexDigestSha1"
|
252 |
+
);
|
253 |
+
return $signatureService->sign($urlEncodedData);
|
254 |
+
}
|
255 |
+
|
256 |
+
private function _underscoreKeys($array)
|
257 |
+
{
|
258 |
+
foreach($array as $key=>$value)
|
259 |
+
{
|
260 |
+
$newKey = Braintree_Util::camelCaseToDelimiter($key, '_');
|
261 |
+
unset($array[$key]);
|
262 |
+
if (is_array($value))
|
263 |
+
{
|
264 |
+
$array[$newKey] = $this->_underscoreKeys($value);
|
265 |
+
}
|
266 |
+
else
|
267 |
+
{
|
268 |
+
$array[$newKey] = $value;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
return $array;
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* @ignore
|
276 |
+
*/
|
277 |
+
private function _hash($string)
|
278 |
+
{
|
279 |
+
return Braintree_Digest::hexDigestSha1($this->_config->privateKey(), $string);
|
280 |
+
}
|
281 |
+
}
|
282 |
+
Braintree_TransparentRedirectGateway::init();
|
lib/Braintree/UnknownPaymentMethod.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree UnknownPaymentMethod module
|
4 |
+
*
|
5 |
+
* @package Braintree
|
6 |
+
* @category Resources
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Manages Braintree UnknownPaymentMethod
|
12 |
+
*
|
13 |
+
* <b>== More information ==</b>
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* @package Braintree
|
17 |
+
* @category Resources
|
18 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
19 |
+
*
|
20 |
+
* @property-read string $token
|
21 |
+
* @property-read string $imageUrl
|
22 |
+
*/
|
23 |
+
class Braintree_UnknownPaymentMethod extends Braintree
|
24 |
+
{
|
25 |
+
|
26 |
+
|
27 |
+
/**
|
28 |
+
* factory method: returns an instance of Braintree_UnknownPaymentMethod
|
29 |
+
* to the requesting method, with populated properties
|
30 |
+
*
|
31 |
+
* @ignore
|
32 |
+
* @return object instance of Braintree_UnknownPaymentMethod
|
33 |
+
*/
|
34 |
+
public static function factory($attributes)
|
35 |
+
{
|
36 |
+
$instance = new self();
|
37 |
+
$values = array_values($attributes);
|
38 |
+
$instance->_initialize(array_shift($values));
|
39 |
+
return $instance;
|
40 |
+
}
|
41 |
+
|
42 |
+
/* instance methods */
|
43 |
+
|
44 |
+
/**
|
45 |
+
* returns false if default is null or false
|
46 |
+
*
|
47 |
+
* @return boolean
|
48 |
+
*/
|
49 |
+
public function isDefault()
|
50 |
+
{
|
51 |
+
return $this->default;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* sets instance properties from an array of values
|
56 |
+
*
|
57 |
+
* @access protected
|
58 |
+
* @param array $unknownPaymentMethodAttribs array of unknownPaymentMethod data
|
59 |
+
* @return none
|
60 |
+
*/
|
61 |
+
protected function _initialize($unknownPaymentMethodAttribs)
|
62 |
+
{
|
63 |
+
// set the attributes
|
64 |
+
$this->imageUrl = 'https://assets.braintreegateway.com/payment_method_logo/unknown.png';
|
65 |
+
$this->_attributes = $unknownPaymentMethodAttribs;
|
66 |
+
}
|
67 |
+
|
68 |
+
}
|
lib/Braintree/Util.php
ADDED
@@ -0,0 +1,332 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Utility methods
|
4 |
+
* PHP version 5
|
5 |
+
*
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
*/
|
8 |
+
|
9 |
+
class Braintree_Util
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* extracts an attribute and returns an array of objects
|
13 |
+
*
|
14 |
+
* extracts the requested element from an array, and converts the contents
|
15 |
+
* of its child arrays to objects of type Braintree_$attributeName, or returns
|
16 |
+
* an array with a single element containing the value of that array element
|
17 |
+
*
|
18 |
+
* @param array $attribArray attributes from a search response
|
19 |
+
* @param string $attributeName indicates which element of the passed array to extract
|
20 |
+
*
|
21 |
+
* @return array array of Braintree_$attributeName objects, or a single element array
|
22 |
+
*/
|
23 |
+
public static function extractAttributeAsArray(& $attribArray, $attributeName)
|
24 |
+
{
|
25 |
+
if(!isset($attribArray[$attributeName])):
|
26 |
+
return array();
|
27 |
+
endif;
|
28 |
+
|
29 |
+
// get what should be an array from the passed array
|
30 |
+
$data = $attribArray[$attributeName];
|
31 |
+
// set up the class that will be used to convert each array element
|
32 |
+
$classFactory = self::buildClassName($attributeName) . '::factory';
|
33 |
+
if(is_array($data)):
|
34 |
+
// create an object from the data in each element
|
35 |
+
$objectArray = array_map($classFactory, $data);
|
36 |
+
else:
|
37 |
+
return array($data);
|
38 |
+
endif;
|
39 |
+
|
40 |
+
unset($attribArray[$attributeName]);
|
41 |
+
return $objectArray;
|
42 |
+
}
|
43 |
+
/**
|
44 |
+
* throws an exception based on the type of error
|
45 |
+
* @param string $statusCode HTTP status code to throw exception from
|
46 |
+
* @throws Braintree_Exception multiple types depending on the error
|
47 |
+
*
|
48 |
+
*/
|
49 |
+
public static function throwStatusCodeException($statusCode, $message=null)
|
50 |
+
{
|
51 |
+
switch($statusCode) {
|
52 |
+
case 401:
|
53 |
+
throw new Braintree_Exception_Authentication();
|
54 |
+
break;
|
55 |
+
case 403:
|
56 |
+
throw new Braintree_Exception_Authorization($message);
|
57 |
+
break;
|
58 |
+
case 404:
|
59 |
+
throw new Braintree_Exception_NotFound();
|
60 |
+
break;
|
61 |
+
case 426:
|
62 |
+
throw new Braintree_Exception_UpgradeRequired();
|
63 |
+
break;
|
64 |
+
case 500:
|
65 |
+
throw new Braintree_Exception_ServerError();
|
66 |
+
break;
|
67 |
+
case 503:
|
68 |
+
throw new Braintree_Exception_DownForMaintenance();
|
69 |
+
break;
|
70 |
+
default:
|
71 |
+
throw new Braintree_Exception_Unexpected('Unexpected HTTP_RESPONSE #'.$statusCode);
|
72 |
+
break;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
*
|
78 |
+
* @param string $className
|
79 |
+
* @param object $resultObj
|
80 |
+
* @return object returns the passed object if successful
|
81 |
+
* @throws Braintree_Exception_ValidationsFailed
|
82 |
+
*/
|
83 |
+
public static function returnObjectOrThrowException($className, $resultObj)
|
84 |
+
{
|
85 |
+
$resultObjName = Braintree_Util::cleanClassName($className);
|
86 |
+
if ($resultObj->success) {
|
87 |
+
return $resultObj->$resultObjName;
|
88 |
+
} else {
|
89 |
+
throw new Braintree_Exception_ValidationsFailed();
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* removes the Braintree_ header from a classname
|
95 |
+
*
|
96 |
+
* @param string $name Braintree_ClassName
|
97 |
+
* @return camelCased classname minus Braintree_ header
|
98 |
+
*/
|
99 |
+
public static function cleanClassName($name)
|
100 |
+
{
|
101 |
+
$classNamesToResponseKeys = array(
|
102 |
+
'CreditCard' => 'creditCard',
|
103 |
+
'CreditCardGateway' => 'creditCard',
|
104 |
+
'Customer' => 'customer',
|
105 |
+
'CustomerGateway' => 'customer',
|
106 |
+
'Subscription' => 'subscription',
|
107 |
+
'SubscriptionGateway' => 'subscription',
|
108 |
+
'Transaction' => 'transaction',
|
109 |
+
'TransactionGateway' => 'transaction',
|
110 |
+
'CreditCardVerification' => 'verification',
|
111 |
+
'CreditCardVerificationGateway' => 'verification',
|
112 |
+
'AddOn' => 'addOn',
|
113 |
+
'AddOnGateway' => 'addOn',
|
114 |
+
'Discount' => 'discount',
|
115 |
+
'DiscountGateway' => 'discount',
|
116 |
+
'Plan' => 'plan',
|
117 |
+
'PlanGateway' => 'plan',
|
118 |
+
'Address' => 'address',
|
119 |
+
'AddressGateway' => 'address',
|
120 |
+
'SettlementBatchSummary' => 'settlementBatchSummary',
|
121 |
+
'SettlementBatchSummaryGateway' => 'settlementBatchSummary',
|
122 |
+
'MerchantAccount' => 'merchantAccount',
|
123 |
+
'MerchantAccountGateway' => 'merchantAccount',
|
124 |
+
'PayPalAccount' => 'paypalAccount',
|
125 |
+
'PayPalAccountGateway' => 'paypalAccount'
|
126 |
+
);
|
127 |
+
|
128 |
+
$name = str_replace('Braintree_', '', $name);
|
129 |
+
return $classNamesToResponseKeys[$name];
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
*
|
134 |
+
* @param string $name className
|
135 |
+
* @return string Braintree_ClassName
|
136 |
+
*/
|
137 |
+
public static function buildClassName($name)
|
138 |
+
{
|
139 |
+
$responseKeysToClassNames = array(
|
140 |
+
'creditCard' => 'CreditCard',
|
141 |
+
'customer' => 'Customer',
|
142 |
+
'subscription' => 'Subscription',
|
143 |
+
'transaction' => 'Transaction',
|
144 |
+
'verification' => 'CreditCardVerification',
|
145 |
+
'addOn' => 'AddOn',
|
146 |
+
'discount' => 'Discount',
|
147 |
+
'plan' => 'Plan',
|
148 |
+
'address' => 'Address',
|
149 |
+
'settlementBatchSummary' => 'SettlementBatchSummary',
|
150 |
+
'merchantAccount' => 'MerchantAccount'
|
151 |
+
);
|
152 |
+
|
153 |
+
return 'Braintree_' . $responseKeysToClassNames[$name];
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* convert alpha-beta-gamma to alphaBetaGamma
|
158 |
+
*
|
159 |
+
* @access public
|
160 |
+
* @param string $string
|
161 |
+
* @return string modified string
|
162 |
+
*/
|
163 |
+
public static function delimiterToCamelCase($string, $delimiter = '[\-\_]')
|
164 |
+
{
|
165 |
+
// php doesn't garbage collect functions created by create_function()
|
166 |
+
// so use a static variable to avoid adding a new function to memory
|
167 |
+
// every time this function is called.
|
168 |
+
static $callback = null;
|
169 |
+
if ($callback === null) {
|
170 |
+
$callback = create_function('$matches', 'return strtoupper($matches[1]);');
|
171 |
+
}
|
172 |
+
|
173 |
+
return preg_replace_callback('/' . $delimiter . '(\w)/', $callback, $string);
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* convert alpha-beta-gamma to alpha_beta_gamma
|
178 |
+
*
|
179 |
+
* @access public
|
180 |
+
* @param string $string
|
181 |
+
* @return string modified string
|
182 |
+
*/
|
183 |
+
public static function delimiterToUnderscore($string)
|
184 |
+
{
|
185 |
+
return preg_replace('/-/', '_', $string);
|
186 |
+
}
|
187 |
+
|
188 |
+
|
189 |
+
/**
|
190 |
+
* find capitals and convert to delimiter + lowercase
|
191 |
+
*
|
192 |
+
* @access public
|
193 |
+
* @param var $string
|
194 |
+
* @return var modified string
|
195 |
+
*/
|
196 |
+
public static function camelCaseToDelimiter($string, $delimiter = '-')
|
197 |
+
{
|
198 |
+
// php doesn't garbage collect functions created by create_function()
|
199 |
+
// so use a static variable to avoid adding a new function to memory
|
200 |
+
// every time this function is called.
|
201 |
+
static $callbacks = array();
|
202 |
+
if (!isset($callbacks[$delimiter])) {
|
203 |
+
$callbacks[$delimiter] = create_function('$matches', "return '$delimiter' . strtolower(\$matches[1]);");
|
204 |
+
}
|
205 |
+
|
206 |
+
return preg_replace_callback('/([A-Z])/', $callbacks[$delimiter], $string);
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
*
|
211 |
+
* @param array $array associative array to implode
|
212 |
+
* @param string $separator (optional, defaults to =)
|
213 |
+
* @param string $glue (optional, defaults to ', ')
|
214 |
+
*/
|
215 |
+
public static function implodeAssociativeArray($array, $separator = '=', $glue = ', ')
|
216 |
+
{
|
217 |
+
// build a new array with joined keys and values
|
218 |
+
$tmpArray = null;
|
219 |
+
foreach ($array AS $key => $value) {
|
220 |
+
$tmpArray[] = $key . $separator . $value;
|
221 |
+
|
222 |
+
}
|
223 |
+
// implode and return the new array
|
224 |
+
return (is_array($tmpArray)) ? implode($glue, $tmpArray) : false;
|
225 |
+
}
|
226 |
+
|
227 |
+
public static function attributesToString($attributes) {
|
228 |
+
$printableAttribs = array();
|
229 |
+
foreach ($attributes AS $key => $value) {
|
230 |
+
if (is_array($value)) {
|
231 |
+
$pAttrib = Braintree_Util::attributesToString($value);
|
232 |
+
} else if ($value instanceof DateTime) {
|
233 |
+
$pAttrib = $value->format(DateTime::RFC850);
|
234 |
+
} else {
|
235 |
+
$pAttrib = $value;
|
236 |
+
}
|
237 |
+
$printableAttribs[$key] = sprintf('%s', $pAttrib);
|
238 |
+
}
|
239 |
+
return Braintree_Util::implodeAssociativeArray($printableAttribs);
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* verify user request structure
|
244 |
+
*
|
245 |
+
* compares the expected signature of a gateway request
|
246 |
+
* against the actual structure sent by the user
|
247 |
+
*
|
248 |
+
* @param array $signature
|
249 |
+
* @param array $attributes
|
250 |
+
*/
|
251 |
+
public static function verifyKeys($signature, $attributes)
|
252 |
+
{
|
253 |
+
$validKeys = self::_flattenArray($signature);
|
254 |
+
$userKeys = self::_flattenUserKeys($attributes);
|
255 |
+
$invalidKeys = array_diff($userKeys, $validKeys);
|
256 |
+
$invalidKeys = self::_removeWildcardKeys($validKeys, $invalidKeys);
|
257 |
+
|
258 |
+
if(!empty($invalidKeys)) {
|
259 |
+
asort($invalidKeys);
|
260 |
+
$sortedList = join(', ', $invalidKeys);
|
261 |
+
throw new InvalidArgumentException('invalid keys: '. $sortedList);
|
262 |
+
}
|
263 |
+
}
|
264 |
+
/**
|
265 |
+
* flattens a numerically indexed nested array to a single level
|
266 |
+
* @param array $keys
|
267 |
+
* @param string $namespace
|
268 |
+
* @return array
|
269 |
+
*/
|
270 |
+
private static function _flattenArray($keys, $namespace = null)
|
271 |
+
{
|
272 |
+
$flattenedArray = array();
|
273 |
+
foreach($keys AS $key) {
|
274 |
+
if(is_array($key)) {
|
275 |
+
$theKeys = array_keys($key);
|
276 |
+
$theValues = array_values($key);
|
277 |
+
$scope = $theKeys[0];
|
278 |
+
$fullKey = empty($namespace) ? $scope : $namespace . '[' . $scope . ']';
|
279 |
+
$flattenedArray = array_merge($flattenedArray, self::_flattenArray($theValues[0], $fullKey));
|
280 |
+
} else {
|
281 |
+
$fullKey = empty($namespace) ? $key : $namespace . '[' . $key . ']';
|
282 |
+
$flattenedArray[] = $fullKey;
|
283 |
+
}
|
284 |
+
}
|
285 |
+
sort($flattenedArray);
|
286 |
+
return $flattenedArray;
|
287 |
+
}
|
288 |
+
|
289 |
+
private static function _flattenUserKeys($keys, $namespace = null)
|
290 |
+
{
|
291 |
+
$flattenedArray = array();
|
292 |
+
|
293 |
+
foreach($keys AS $key => $value) {
|
294 |
+
$fullKey = empty($namespace) ? $key : $namespace;
|
295 |
+
if (!is_numeric($key) && $namespace != null) {
|
296 |
+
$fullKey .= '[' . $key . ']';
|
297 |
+
}
|
298 |
+
if (is_numeric($key) && is_string($value)) {
|
299 |
+
$fullKey .= '[' . $value . ']';
|
300 |
+
}
|
301 |
+
if(is_array($value)) {
|
302 |
+
$more = self::_flattenUserKeys($value, $fullKey);
|
303 |
+
$flattenedArray = array_merge($flattenedArray, $more);
|
304 |
+
} else {
|
305 |
+
$flattenedArray[] = $fullKey;
|
306 |
+
}
|
307 |
+
}
|
308 |
+
sort($flattenedArray);
|
309 |
+
return $flattenedArray;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* removes wildcard entries from the invalid keys array
|
314 |
+
* @param array $validKeys
|
315 |
+
* @param <array $invalidKeys
|
316 |
+
* @return array
|
317 |
+
*/
|
318 |
+
private static function _removeWildcardKeys($validKeys, $invalidKeys)
|
319 |
+
{
|
320 |
+
foreach($validKeys AS $key) {
|
321 |
+
if (stristr($key, '[_anyKey_]')) {
|
322 |
+
$wildcardKey = str_replace('[_anyKey_]', '', $key);
|
323 |
+
foreach ($invalidKeys AS $index => $invalidKey) {
|
324 |
+
if (stristr($invalidKey, $wildcardKey)) {
|
325 |
+
unset($invalidKeys[$index]);
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
}
|
330 |
+
return $invalidKeys;
|
331 |
+
}
|
332 |
+
}
|
lib/Braintree/Version.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Library Version
|
4 |
+
* stores version information about the Braintree library
|
5 |
+
*
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
*/
|
8 |
+
final class Braintree_Version
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* class constants
|
12 |
+
*/
|
13 |
+
const MAJOR = 2;
|
14 |
+
const MINOR = 37;
|
15 |
+
const TINY = 0;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @ignore
|
19 |
+
* @access protected
|
20 |
+
*/
|
21 |
+
protected function __construct()
|
22 |
+
{
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
*
|
27 |
+
* @return string the current library version
|
28 |
+
*/
|
29 |
+
public static function get()
|
30 |
+
{
|
31 |
+
return self::MAJOR.'.'.self::MINOR.'.'.self::TINY;
|
32 |
+
}
|
33 |
+
}
|
lib/Braintree/WebhookNotification.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_WebhookNotification extends Braintree
|
3 |
+
{
|
4 |
+
const SUBSCRIPTION_CANCELED = 'subscription_canceled';
|
5 |
+
const SUBSCRIPTION_CHARGED_SUCCESSFULLY = 'subscription_charged_successfully';
|
6 |
+
const SUBSCRIPTION_CHARGED_UNSUCCESSFULLY = 'subscription_charged_unsuccessfully';
|
7 |
+
const SUBSCRIPTION_EXPIRED = 'subscription_expired';
|
8 |
+
const SUBSCRIPTION_TRIAL_ENDED = 'subscription_trial_ended';
|
9 |
+
const SUBSCRIPTION_WENT_ACTIVE = 'subscription_went_active';
|
10 |
+
const SUBSCRIPTION_WENT_PAST_DUE = 'subscription_went_past_due';
|
11 |
+
const SUB_MERCHANT_ACCOUNT_APPROVED = 'sub_merchant_account_approved';
|
12 |
+
const SUB_MERCHANT_ACCOUNT_DECLINED = 'sub_merchant_account_declined';
|
13 |
+
const TRANSACTION_DISBURSED = 'transaction_disbursed';
|
14 |
+
const DISBURSEMENT_EXCEPTION = 'disbursement_exception';
|
15 |
+
const DISBURSEMENT = 'disbursement';
|
16 |
+
const DISPUTE_OPENED = 'dispute_opened';
|
17 |
+
const DISPUTE_LOST = 'dispute_lost';
|
18 |
+
const DISPUTE_WON = 'dispute_won';
|
19 |
+
const PARTNER_MERCHANT_CONNECTED = 'partner_merchant_connected';
|
20 |
+
const PARTNER_MERCHANT_DISCONNECTED = 'partner_merchant_disconnected';
|
21 |
+
const PARTNER_MERCHANT_DECLINED = 'partner_merchant_declined';
|
22 |
+
|
23 |
+
public static function parse($signature, $payload)
|
24 |
+
{
|
25 |
+
if (preg_match("/[^A-Za-z0-9+=\/\n]/", $payload) === 1) {
|
26 |
+
throw new Braintree_Exception_InvalidSignature("payload contains illegal characters");
|
27 |
+
}
|
28 |
+
self::_validateSignature($signature, $payload);
|
29 |
+
|
30 |
+
$xml = base64_decode($payload);
|
31 |
+
$attributes = Braintree_Xml::buildArrayFromXml($xml);
|
32 |
+
return self::factory($attributes['notification']);
|
33 |
+
}
|
34 |
+
|
35 |
+
public static function verify($challenge)
|
36 |
+
{
|
37 |
+
$publicKey = Braintree_Configuration::publicKey();
|
38 |
+
$digest = Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $challenge);
|
39 |
+
return "{$publicKey}|{$digest}";
|
40 |
+
}
|
41 |
+
|
42 |
+
public static function factory($attributes)
|
43 |
+
{
|
44 |
+
$instance = new self();
|
45 |
+
$instance->_initialize($attributes);
|
46 |
+
return $instance;
|
47 |
+
}
|
48 |
+
|
49 |
+
private static function _matchingSignature($signaturePairs)
|
50 |
+
{
|
51 |
+
foreach ($signaturePairs as $pair)
|
52 |
+
{
|
53 |
+
$components = preg_split("/\|/", $pair);
|
54 |
+
if ($components[0] == Braintree_Configuration::publicKey()) {
|
55 |
+
return $components[1];
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
return null;
|
60 |
+
}
|
61 |
+
|
62 |
+
private static function _payloadMatches($signature, $payload)
|
63 |
+
{
|
64 |
+
$payloadSignature = Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $payload);
|
65 |
+
return Braintree_Digest::secureCompare($signature, $payloadSignature);
|
66 |
+
}
|
67 |
+
|
68 |
+
private static function _validateSignature($signatureString, $payload)
|
69 |
+
{
|
70 |
+
$signaturePairs = preg_split("/&/", $signatureString);
|
71 |
+
$signature = self::_matchingSignature($signaturePairs);
|
72 |
+
if (!$signature) {
|
73 |
+
throw new Braintree_Exception_InvalidSignature("no matching public key");
|
74 |
+
}
|
75 |
+
|
76 |
+
if (!(self::_payloadMatches($signature, $payload) || self::_payloadMatches($signature, $payload . "\n"))) {
|
77 |
+
throw new Braintree_Exception_InvalidSignature("signature does not match payload - one has been modified");
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
protected function _initialize($attributes)
|
82 |
+
{
|
83 |
+
$this->_attributes = $attributes;
|
84 |
+
|
85 |
+
if (isset($attributes['subject']['apiErrorResponse'])) {
|
86 |
+
$wrapperNode = $attributes['subject']['apiErrorResponse'];
|
87 |
+
} else {
|
88 |
+
$wrapperNode = $attributes['subject'];
|
89 |
+
}
|
90 |
+
|
91 |
+
if (isset($wrapperNode['subscription'])) {
|
92 |
+
$this->_set('subscription', Braintree_Subscription::factory($attributes['subject']['subscription']));
|
93 |
+
}
|
94 |
+
|
95 |
+
if (isset($wrapperNode['merchantAccount'])) {
|
96 |
+
$this->_set('merchantAccount', Braintree_MerchantAccount::factory($wrapperNode['merchantAccount']));
|
97 |
+
}
|
98 |
+
|
99 |
+
if (isset($wrapperNode['transaction'])) {
|
100 |
+
$this->_set('transaction', Braintree_Transaction::factory($wrapperNode['transaction']));
|
101 |
+
}
|
102 |
+
|
103 |
+
if (isset($wrapperNode['disbursement'])) {
|
104 |
+
$this->_set('disbursement', Braintree_Disbursement::factory($wrapperNode['disbursement']));
|
105 |
+
}
|
106 |
+
|
107 |
+
if (isset($wrapperNode['partnerMerchant'])) {
|
108 |
+
$this->_set('partnerMerchant', Braintree_PartnerMerchant::factory($wrapperNode['partnerMerchant']));
|
109 |
+
}
|
110 |
+
|
111 |
+
if (isset($wrapperNode['dispute'])) {
|
112 |
+
$this->_set('dispute', Braintree_PartnerMerchant::factory($wrapperNode['dispute']));
|
113 |
+
}
|
114 |
+
|
115 |
+
if (isset($wrapperNode['errors'])) {
|
116 |
+
$this->_set('errors', new Braintree_Error_ValidationErrorCollection($wrapperNode['errors']));
|
117 |
+
$this->_set('message', $wrapperNode['message']);
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
lib/Braintree/WebhookTesting.php
ADDED
@@ -0,0 +1,283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Braintree_WebhookTesting
|
3 |
+
{
|
4 |
+
public static function sampleNotification($kind, $id)
|
5 |
+
{
|
6 |
+
$payload = base64_encode(self::_sampleXml($kind, $id)) . "\n";
|
7 |
+
$signature = Braintree_Configuration::publicKey() . "|" . Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $payload);
|
8 |
+
|
9 |
+
return array(
|
10 |
+
'bt_signature' => $signature,
|
11 |
+
'bt_payload' => $payload
|
12 |
+
);
|
13 |
+
}
|
14 |
+
|
15 |
+
private static function _sampleXml($kind, $id)
|
16 |
+
{
|
17 |
+
switch ($kind) {
|
18 |
+
case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED:
|
19 |
+
$subjectXml = self::_merchantAccountApprovedSampleXml($id);
|
20 |
+
break;
|
21 |
+
case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED:
|
22 |
+
$subjectXml = self::_merchantAccountDeclinedSampleXml($id);
|
23 |
+
break;
|
24 |
+
case Braintree_WebhookNotification::TRANSACTION_DISBURSED:
|
25 |
+
$subjectXml = self::_transactionDisbursedSampleXml($id);
|
26 |
+
break;
|
27 |
+
case Braintree_WebhookNotification::DISBURSEMENT_EXCEPTION:
|
28 |
+
$subjectXml = self::_disbursementExceptionSampleXml($id);
|
29 |
+
break;
|
30 |
+
case Braintree_WebhookNotification::DISBURSEMENT:
|
31 |
+
$subjectXml = self::_disbursementSampleXml($id);
|
32 |
+
break;
|
33 |
+
case Braintree_WebhookNotification::PARTNER_MERCHANT_CONNECTED:
|
34 |
+
$subjectXml = self::_partnerMerchantConnectedSampleXml($id);
|
35 |
+
break;
|
36 |
+
case Braintree_WebhookNotification::PARTNER_MERCHANT_DISCONNECTED:
|
37 |
+
$subjectXml = self::_partnerMerchantDisconnectedSampleXml($id);
|
38 |
+
break;
|
39 |
+
case Braintree_WebhookNotification::PARTNER_MERCHANT_DECLINED:
|
40 |
+
$subjectXml = self::_partnerMerchantDeclinedSampleXml($id);
|
41 |
+
break;
|
42 |
+
case Braintree_WebhookNotification::DISPUTE_OPENED:
|
43 |
+
$subjectXml = self::_disputeOpenedSampleXml($id);
|
44 |
+
break;
|
45 |
+
case Braintree_WebhookNotification::DISPUTE_LOST:
|
46 |
+
$subjectXml = self::_disputeLostSampleXml($id);
|
47 |
+
break;
|
48 |
+
case Braintree_WebhookNotification::DISPUTE_WON:
|
49 |
+
$subjectXml = self::_disputeWonSampleXml($id);
|
50 |
+
break;
|
51 |
+
default:
|
52 |
+
$subjectXml = self::_subscriptionSampleXml($id);
|
53 |
+
break;
|
54 |
+
}
|
55 |
+
$timestamp = self::_timestamp();
|
56 |
+
return "
|
57 |
+
<notification>
|
58 |
+
<timestamp type=\"datetime\">{$timestamp}</timestamp>
|
59 |
+
<kind>{$kind}</kind>
|
60 |
+
<subject>{$subjectXml}</subject>
|
61 |
+
</notification>
|
62 |
+
";
|
63 |
+
}
|
64 |
+
|
65 |
+
private static function _merchantAccountApprovedSampleXml($id)
|
66 |
+
{
|
67 |
+
return "
|
68 |
+
<merchant_account>
|
69 |
+
<id>{$id}</id>
|
70 |
+
<master_merchant_account>
|
71 |
+
<id>master_ma_for_{$id}</id>
|
72 |
+
<status>active</status>
|
73 |
+
</master_merchant_account>
|
74 |
+
<status>active</status>
|
75 |
+
</merchant_account>
|
76 |
+
";
|
77 |
+
}
|
78 |
+
|
79 |
+
private static function _merchantAccountDeclinedSampleXml($id)
|
80 |
+
{
|
81 |
+
return "
|
82 |
+
<api-error-response>
|
83 |
+
<message>Credit score is too low</message>
|
84 |
+
<errors>
|
85 |
+
<errors type=\"array\"/>
|
86 |
+
<merchant-account>
|
87 |
+
<errors type=\"array\">
|
88 |
+
<error>
|
89 |
+
<code>82621</code>
|
90 |
+
<message>Credit score is too low</message>
|
91 |
+
<attribute type=\"symbol\">base</attribute>
|
92 |
+
</error>
|
93 |
+
</errors>
|
94 |
+
</merchant-account>
|
95 |
+
</errors>
|
96 |
+
<merchant-account>
|
97 |
+
<id>{$id}</id>
|
98 |
+
<status>suspended</status>
|
99 |
+
<master-merchant-account>
|
100 |
+
<id>master_ma_for_{$id}</id>
|
101 |
+
<status>suspended</status>
|
102 |
+
</master-merchant-account>
|
103 |
+
</merchant-account>
|
104 |
+
</api-error-response>
|
105 |
+
";
|
106 |
+
}
|
107 |
+
|
108 |
+
private static function _transactionDisbursedSampleXml($id)
|
109 |
+
{
|
110 |
+
return "
|
111 |
+
<transaction>
|
112 |
+
<id>${id}</id>
|
113 |
+
<amount>100</amount>
|
114 |
+
<disbursement-details>
|
115 |
+
<disbursement-date type=\"date\">2013-07-09</disbursement-date>
|
116 |
+
</disbursement-details>
|
117 |
+
</transaction>
|
118 |
+
";
|
119 |
+
}
|
120 |
+
|
121 |
+
private static function _disbursementExceptionSampleXml($id)
|
122 |
+
{
|
123 |
+
return "
|
124 |
+
<disbursement>
|
125 |
+
<id>${id}</id>
|
126 |
+
<transaction-ids type=\"array\">
|
127 |
+
<item>asdfg</item>
|
128 |
+
<item>qwert</item>
|
129 |
+
</transaction-ids>
|
130 |
+
<success type=\"boolean\">false</success>
|
131 |
+
<retry type=\"boolean\">false</retry>
|
132 |
+
<merchant-account>
|
133 |
+
<id>merchant_account_token</id>
|
134 |
+
<currency-iso-code>USD</currency-iso-code>
|
135 |
+
<sub-merchant-account type=\"boolean\">false</sub-merchant-account>
|
136 |
+
<status>active</status>
|
137 |
+
</merchant-account>
|
138 |
+
<amount>100.00</amount>
|
139 |
+
<disbursement-date type=\"date\">2014-02-10</disbursement-date>
|
140 |
+
<exception-message>bank_rejected</exception-message>
|
141 |
+
<follow-up-action>update_funding_information</follow-up-action>
|
142 |
+
</disbursement>
|
143 |
+
";
|
144 |
+
}
|
145 |
+
|
146 |
+
private static function _disbursementSampleXml($id)
|
147 |
+
{
|
148 |
+
return "
|
149 |
+
<disbursement>
|
150 |
+
<id>${id}</id>
|
151 |
+
<transaction-ids type=\"array\">
|
152 |
+
<item>asdfg</item>
|
153 |
+
<item>qwert</item>
|
154 |
+
</transaction-ids>
|
155 |
+
<success type=\"boolean\">true</success>
|
156 |
+
<retry type=\"boolean\">false</retry>
|
157 |
+
<merchant-account>
|
158 |
+
<id>merchant_account_token</id>
|
159 |
+
<currency-iso-code>USD</currency-iso-code>
|
160 |
+
<sub-merchant-account type=\"boolean\">false</sub-merchant-account>
|
161 |
+
<status>active</status>
|
162 |
+
</merchant-account>
|
163 |
+
<amount>100.00</amount>
|
164 |
+
<disbursement-date type=\"date\">2014-02-10</disbursement-date>
|
165 |
+
<exception-message nil=\"true\"/>
|
166 |
+
<follow-up-action nil=\"true\"/>
|
167 |
+
</disbursement>
|
168 |
+
";
|
169 |
+
}
|
170 |
+
|
171 |
+
private static function _disputeOpenedSampleXml($id)
|
172 |
+
{
|
173 |
+
return "
|
174 |
+
<dispute>
|
175 |
+
<amount>250.00</amount>
|
176 |
+
<currency-iso-code>USD</currency-iso-code>
|
177 |
+
<received-date type=\"date\">2014-03-01</received-date>
|
178 |
+
<reply-by-date type=\"date\">2014-03-21</reply-by-date>
|
179 |
+
<status>open</status>
|
180 |
+
<reason>fraud</reason>
|
181 |
+
<id>${id}</id>
|
182 |
+
<transaction>
|
183 |
+
<id>${id}</id>
|
184 |
+
<amount>250.00</amount>
|
185 |
+
</transaction>
|
186 |
+
</dispute>
|
187 |
+
";
|
188 |
+
}
|
189 |
+
|
190 |
+
private static function _disputeLostSampleXml($id)
|
191 |
+
{
|
192 |
+
return "
|
193 |
+
<dispute>
|
194 |
+
<amount>250.00</amount>
|
195 |
+
<currency-iso-code>USD</currency-iso-code>
|
196 |
+
<received-date type=\"date\">2014-03-01</received-date>
|
197 |
+
<reply-by-date type=\"date\">2014-03-21</reply-by-date>
|
198 |
+
<status>lost</status>
|
199 |
+
<reason>fraud</reason>
|
200 |
+
<id>${id}</id>
|
201 |
+
<transaction>
|
202 |
+
<id>${id}</id>
|
203 |
+
<amount>250.00</amount>
|
204 |
+
</transaction>
|
205 |
+
</dispute>
|
206 |
+
";
|
207 |
+
}
|
208 |
+
|
209 |
+
private static function _disputeWonSampleXml($id)
|
210 |
+
{
|
211 |
+
return "
|
212 |
+
<dispute>
|
213 |
+
<amount>250.00</amount>
|
214 |
+
<currency-iso-code>USD</currency-iso-code>
|
215 |
+
<received-date type=\"date\">2014-03-01</received-date>
|
216 |
+
<reply-by-date type=\"date\">2014-03-21</reply-by-date>
|
217 |
+
<status>won</status>
|
218 |
+
<reason>fraud</reason>
|
219 |
+
<id>${id}</id>
|
220 |
+
<transaction>
|
221 |
+
<id>${id}</id>
|
222 |
+
<amount>250.00</amount>
|
223 |
+
</transaction>
|
224 |
+
</dispute>
|
225 |
+
";
|
226 |
+
}
|
227 |
+
|
228 |
+
private static function _subscriptionSampleXml($id)
|
229 |
+
{
|
230 |
+
return "
|
231 |
+
<subscription>
|
232 |
+
<id>{$id}</id>
|
233 |
+
<transactions type=\"array\">
|
234 |
+
</transactions>
|
235 |
+
<add_ons type=\"array\">
|
236 |
+
</add_ons>
|
237 |
+
<discounts type=\"array\">
|
238 |
+
</discounts>
|
239 |
+
</subscription>
|
240 |
+
";
|
241 |
+
}
|
242 |
+
|
243 |
+
private static function _partnerMerchantConnectedSampleXml($id)
|
244 |
+
{
|
245 |
+
return "
|
246 |
+
<partner-merchant>
|
247 |
+
<merchant-public-id>public_id</merchant-public-id>
|
248 |
+
<public-key>public_key</public-key>
|
249 |
+
<private-key>private_key</private-key>
|
250 |
+
<partner-merchant-id>abc123</partner-merchant-id>
|
251 |
+
<client-side-encryption-key>cse_key</client-side-encryption-key>
|
252 |
+
</partner-merchant>
|
253 |
+
";
|
254 |
+
}
|
255 |
+
|
256 |
+
private static function _partnerMerchantDisconnectedSampleXml($id)
|
257 |
+
{
|
258 |
+
return "
|
259 |
+
<partner-merchant>
|
260 |
+
<partner-merchant-id>abc123</partner-merchant-id>
|
261 |
+
</partner-merchant>
|
262 |
+
";
|
263 |
+
}
|
264 |
+
|
265 |
+
private static function _partnerMerchantDeclinedSampleXml($id)
|
266 |
+
{
|
267 |
+
return "
|
268 |
+
<partner-merchant>
|
269 |
+
<partner-merchant-id>abc123</partner-merchant-id>
|
270 |
+
</partner-merchant>
|
271 |
+
";
|
272 |
+
}
|
273 |
+
|
274 |
+
private static function _timestamp()
|
275 |
+
{
|
276 |
+
$originalZone = date_default_timezone_get();
|
277 |
+
date_default_timezone_set('UTC');
|
278 |
+
$timestamp = strftime('%Y-%m-%dT%TZ');
|
279 |
+
date_default_timezone_set($originalZone);
|
280 |
+
|
281 |
+
return $timestamp;
|
282 |
+
}
|
283 |
+
}
|
lib/Braintree/Xml.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Braintree Xml parser and generator
|
4 |
+
* PHP version 5
|
5 |
+
* superclass for Braintree XML parsing and generation
|
6 |
+
*
|
7 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
8 |
+
*/
|
9 |
+
final class Braintree_Xml
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* @ignore
|
13 |
+
*/
|
14 |
+
protected function __construct()
|
15 |
+
{
|
16 |
+
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
*
|
21 |
+
* @param string $xml
|
22 |
+
* @return array
|
23 |
+
*/
|
24 |
+
public static function buildArrayFromXml($xml)
|
25 |
+
{
|
26 |
+
return Braintree_Xml_Parser::arrayFromXml($xml);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
*
|
31 |
+
* @param array $array
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
public static function buildXmlFromArray($array)
|
35 |
+
{
|
36 |
+
return Braintree_Xml_Generator::arrayToXml($array);
|
37 |
+
}
|
38 |
+
}
|
lib/Braintree/Xml/Generator.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* PHP version 5
|
4 |
+
*
|
5 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Generates XML output from arrays using PHP's
|
10 |
+
* built-in XMLWriter
|
11 |
+
*
|
12 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
13 |
+
*/
|
14 |
+
class Braintree_Xml_Generator
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* arrays passed to this method should have a single root element
|
18 |
+
* with an array as its value
|
19 |
+
* @param array $aData the array of data
|
20 |
+
* @return var XML string
|
21 |
+
*/
|
22 |
+
public static function arrayToXml($aData)
|
23 |
+
{
|
24 |
+
// set up the XMLWriter
|
25 |
+
$writer = new XMLWriter();
|
26 |
+
$writer->openMemory();
|
27 |
+
|
28 |
+
$writer->setIndent(true);
|
29 |
+
$writer->setIndentString(' ');
|
30 |
+
$writer->startDocument('1.0', 'UTF-8');
|
31 |
+
|
32 |
+
// get the root element name
|
33 |
+
$aKeys = array_keys($aData);
|
34 |
+
$rootElementName = $aKeys[0];
|
35 |
+
// open the root element
|
36 |
+
$writer->startElement(Braintree_Util::camelCaseToDelimiter($rootElementName));
|
37 |
+
// create the body
|
38 |
+
self::_createElementsFromArray($writer, $aData[$rootElementName], $rootElementName);
|
39 |
+
|
40 |
+
// close the root element and document
|
41 |
+
$writer->endElement();
|
42 |
+
$writer->endDocument();
|
43 |
+
|
44 |
+
// send the output as string
|
45 |
+
return $writer->outputMemory();
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Construct XML elements with attributes from an associative array.
|
50 |
+
*
|
51 |
+
* @access protected
|
52 |
+
* @static
|
53 |
+
* @param object $writer XMLWriter object
|
54 |
+
* @param array $aData contains attributes and values
|
55 |
+
* @return none
|
56 |
+
*/
|
57 |
+
private static function _createElementsFromArray(&$writer, $aData)
|
58 |
+
{
|
59 |
+
if (!is_array($aData)) {
|
60 |
+
if (is_bool($aData)) {
|
61 |
+
$writer->text($aData ? 'true' : 'false');
|
62 |
+
} else {
|
63 |
+
$writer->text($aData);
|
64 |
+
}
|
65 |
+
return;
|
66 |
+
}
|
67 |
+
foreach ($aData AS $index => $element) {
|
68 |
+
// convert the style back to gateway format
|
69 |
+
$elementName = Braintree_Util::camelCaseToDelimiter($index, '-');
|
70 |
+
// handle child elements
|
71 |
+
$writer->startElement($elementName);
|
72 |
+
if (is_array($element)) {
|
73 |
+
if (array_key_exists(0, $element) || empty($element)) {
|
74 |
+
$writer->writeAttribute('type', 'array');
|
75 |
+
foreach ($element AS $ignored => $itemInArray) {
|
76 |
+
$writer->startElement('item');
|
77 |
+
self::_createElementsFromArray($writer, $itemInArray);
|
78 |
+
$writer->endElement();
|
79 |
+
}
|
80 |
+
}
|
81 |
+
else {
|
82 |
+
self::_createElementsFromArray($writer, $element);
|
83 |
+
}
|
84 |
+
} else {
|
85 |
+
// generate attributes as needed
|
86 |
+
$attribute = self::_generateXmlAttribute($element);
|
87 |
+
if (is_array($attribute)) {
|
88 |
+
$writer->writeAttribute($attribute[0], $attribute[1]);
|
89 |
+
$element = $attribute[2];
|
90 |
+
}
|
91 |
+
$writer->text($element);
|
92 |
+
}
|
93 |
+
$writer->endElement();
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* convert passed data into an array of attributeType, attributeName, and value
|
99 |
+
* dates sent as DateTime objects will be converted to strings
|
100 |
+
* @access protected
|
101 |
+
* @param mixed $value
|
102 |
+
* @return array attributes and element value
|
103 |
+
*/
|
104 |
+
private static function _generateXmlAttribute($value)
|
105 |
+
{
|
106 |
+
if ($value instanceof DateTime) {
|
107 |
+
return array('type', 'datetime', self::_dateTimeToXmlTimestamp($value));
|
108 |
+
}
|
109 |
+
if (is_int($value)) {
|
110 |
+
return array('type', 'integer', $value);
|
111 |
+
}
|
112 |
+
if (is_bool($value)) {
|
113 |
+
return array('type', 'boolean', ($value ? 'true' : 'false'));
|
114 |
+
}
|
115 |
+
if ($value === NULL) {
|
116 |
+
return array('nil', 'true', $value);
|
117 |
+
}
|
118 |
+
}
|
119 |
+
/**
|
120 |
+
* converts datetime back to xml schema format
|
121 |
+
* @access protected
|
122 |
+
* @param object $dateTime
|
123 |
+
* @return var XML schema formatted timestamp
|
124 |
+
*/
|
125 |
+
private static function _dateTimeToXmlTimestamp($dateTime)
|
126 |
+
{
|
127 |
+
$dateTime->setTimeZone(new DateTimeZone('UTC'));
|
128 |
+
return ($dateTime->format('Y-m-d\TH:i:s') . 'Z');
|
129 |
+
}
|
130 |
+
|
131 |
+
private static function _castDateTime($string)
|
132 |
+
{
|
133 |
+
try {
|
134 |
+
if (empty($string)) {
|
135 |
+
return false;
|
136 |
+
}
|
137 |
+
$dateTime = new DateTime($string);
|
138 |
+
return self::_dateTimeToXmlTimestamp($dateTime);
|
139 |
+
} catch (Exception $e) {
|
140 |
+
// not a datetime
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
lib/Braintree/Xml/Parser.php
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Braintree XML Parser
|
5 |
+
*
|
6 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
7 |
+
*/
|
8 |
+
/**
|
9 |
+
* Parses incoming Xml into arrays using PHP's
|
10 |
+
* built-in SimpleXML, and its extension via
|
11 |
+
* Iterator, SimpleXMLIterator
|
12 |
+
*
|
13 |
+
* @copyright 2014 Braintree, a division of PayPal, Inc.
|
14 |
+
*/
|
15 |
+
class Braintree_Xml_Parser
|
16 |
+
{
|
17 |
+
|
18 |
+
private static $_xmlRoot;
|
19 |
+
private static $_responseType;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* sets up the SimpleXMLIterator and starts the parsing
|
23 |
+
* @access public
|
24 |
+
* @param string $xml
|
25 |
+
* @return array array mapped to the passed xml
|
26 |
+
*/
|
27 |
+
public static function arrayFromXml($xml)
|
28 |
+
{
|
29 |
+
// SimpleXML provides the root information on construct
|
30 |
+
$iterator = new SimpleXMLIterator($xml);
|
31 |
+
$xmlRoot = Braintree_Util::delimiterToCamelCase($iterator->getName());
|
32 |
+
$type = $iterator->attributes()->type;
|
33 |
+
|
34 |
+
self::$_xmlRoot = $iterator->getName();
|
35 |
+
self::$_responseType = $type;
|
36 |
+
|
37 |
+
// return the mapped array with the root element as the header
|
38 |
+
return array($xmlRoot => self::_iteratorToArray($iterator));
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* processes SimpleXMLIterator objects recursively
|
44 |
+
*
|
45 |
+
* @access protected
|
46 |
+
* @param object $iterator
|
47 |
+
* @return array xml converted to array
|
48 |
+
*/
|
49 |
+
private static function _iteratorToArray($iterator)
|
50 |
+
{
|
51 |
+
$xmlArray = array();
|
52 |
+
$value = null;
|
53 |
+
|
54 |
+
// rewind the iterator and check if the position is valid
|
55 |
+
// if not, return the string it contains
|
56 |
+
$iterator->rewind();
|
57 |
+
if (!$iterator->valid()) {
|
58 |
+
return self::_typecastXmlValue($iterator);
|
59 |
+
}
|
60 |
+
for ($iterator->rewind(); $iterator->valid(); $iterator->next()) {
|
61 |
+
|
62 |
+
$tmpArray = null;
|
63 |
+
$value = null;
|
64 |
+
|
65 |
+
// get the attribute type string for use in conditions below
|
66 |
+
$attributeType = $iterator->attributes()->type;
|
67 |
+
|
68 |
+
// extract the parent element via xpath query
|
69 |
+
$parentElement = $iterator->xpath($iterator->key() . '/..');
|
70 |
+
if ($parentElement[0] instanceof SimpleXMLIterator) {
|
71 |
+
$parentElement = $parentElement[0];
|
72 |
+
$parentKey = Braintree_Util::delimiterToCamelCase($parentElement->getName());
|
73 |
+
} else {
|
74 |
+
$parentElement = null;
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
if ($parentKey == "customFields") {
|
79 |
+
$key = Braintree_Util::delimiterToUnderscore($iterator->key());
|
80 |
+
} else {
|
81 |
+
$key = Braintree_Util::delimiterToCamelCase($iterator->key());
|
82 |
+
}
|
83 |
+
|
84 |
+
// process children recursively
|
85 |
+
if ($iterator->hasChildren()) {
|
86 |
+
// return the child elements
|
87 |
+
$value = self::_iteratorToArray($iterator->current());
|
88 |
+
|
89 |
+
// if the element is an array type,
|
90 |
+
// use numeric keys to allow multiple values
|
91 |
+
if ($attributeType != 'array') {
|
92 |
+
$tmpArray[$key] = $value;
|
93 |
+
}
|
94 |
+
} else {
|
95 |
+
// cast values according to attributes
|
96 |
+
$tmpArray[$key] = self::_typecastXmlValue($iterator->current());
|
97 |
+
}
|
98 |
+
|
99 |
+
// set the output string
|
100 |
+
$output = isset($value) ? $value : $tmpArray[$key];
|
101 |
+
|
102 |
+
// determine if there are multiple tags of this name at the same level
|
103 |
+
if (isset($parentElement) &&
|
104 |
+
($parentElement->attributes()->type == 'collection') &&
|
105 |
+
$iterator->hasChildren()) {
|
106 |
+
$xmlArray[$key][] = $output;
|
107 |
+
continue;
|
108 |
+
}
|
109 |
+
|
110 |
+
// if the element was an array type, output to a numbered key
|
111 |
+
// otherwise, use the element name
|
112 |
+
if ($attributeType == 'array') {
|
113 |
+
$xmlArray[] = $output;
|
114 |
+
} else {
|
115 |
+
$xmlArray[$key] = $output;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
return $xmlArray;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* typecast xml value based on attributes
|
124 |
+
* @param object $valueObj SimpleXMLElement
|
125 |
+
* @return mixed value for placing into array
|
126 |
+
*/
|
127 |
+
private static function _typecastXmlValue($valueObj)
|
128 |
+
{
|
129 |
+
// get the element attributes
|
130 |
+
$attribs = $valueObj->attributes();
|
131 |
+
// the element is null, so jump out here
|
132 |
+
if (isset($attribs->nil) && $attribs->nil) {
|
133 |
+
return null;
|
134 |
+
}
|
135 |
+
// switch on the type attribute
|
136 |
+
// switch works even if $attribs->type isn't set
|
137 |
+
switch ($attribs->type) {
|
138 |
+
case 'datetime':
|
139 |
+
return self::_timestampToUTC((string) $valueObj);
|
140 |
+
break;
|
141 |
+
case 'date':
|
142 |
+
return new DateTime((string)$valueObj);
|
143 |
+
break;
|
144 |
+
case 'integer':
|
145 |
+
return (int) $valueObj;
|
146 |
+
break;
|
147 |
+
case 'boolean':
|
148 |
+
$value = (string) $valueObj;
|
149 |
+
// look for a number inside the string
|
150 |
+
if(is_numeric($value)) {
|
151 |
+
return (bool) $value;
|
152 |
+
} else {
|
153 |
+
// look for the string "true", return false in all other cases
|
154 |
+
return ($value != "true") ? FALSE : TRUE;
|
155 |
+
}
|
156 |
+
break;
|
157 |
+
case 'array':
|
158 |
+
return array();
|
159 |
+
default:
|
160 |
+
return (string) $valueObj;
|
161 |
+
}
|
162 |
+
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* convert xml timestamps into DateTime
|
167 |
+
* @param string $timestamp
|
168 |
+
* @return string UTC formatted datetime string
|
169 |
+
*/
|
170 |
+
private static function _timestampToUTC($timestamp)
|
171 |
+
{
|
172 |
+
$tz = new DateTimeZone('UTC');
|
173 |
+
// strangely DateTime requires an explicit set below
|
174 |
+
// to show the proper time zone
|
175 |
+
$dateTime = new DateTime($timestamp, $tz);
|
176 |
+
$dateTime->setTimezone($tz);
|
177 |
+
return $dateTime;
|
178 |
+
}
|
179 |
+
}
|
lib/ssl/api_braintreegateway_com.ca.crt
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-----BEGIN CERTIFICATE-----
|
2 |
+
MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
|
3 |
+
BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
|
4 |
+
c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
|
5 |
+
MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
|
6 |
+
emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
|
7 |
+
DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
|
8 |
+
FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
|
9 |
+
UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
|
10 |
+
YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
|
11 |
+
MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
|
12 |
+
AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
|
13 |
+
pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
|
14 |
+
13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
|
15 |
+
AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
|
16 |
+
U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
|
17 |
+
F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
|
18 |
+
oJ2daZH9
|
19 |
+
-----END CERTIFICATE-----
|
20 |
+
-----BEGIN CERTIFICATE-----
|
21 |
+
MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
|
22 |
+
CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
|
23 |
+
cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
|
24 |
+
LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
|
25 |
+
aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
|
26 |
+
dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
|
27 |
+
VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
|
28 |
+
aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
|
29 |
+
bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
|
30 |
+
IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
|
31 |
+
LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
|
32 |
+
N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
|
33 |
+
KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
|
34 |
+
kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
|
35 |
+
CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
|
36 |
+
Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
|
37 |
+
imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
|
38 |
+
2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
|
39 |
+
DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
|
40 |
+
/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
|
41 |
+
F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
|
42 |
+
TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
|
43 |
+
-----END CERTIFICATE-----
|
44 |
+
-----BEGIN CERTIFICATE-----
|
45 |
+
MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
|
46 |
+
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
|
47 |
+
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
|
48 |
+
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
|
49 |
+
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
|
50 |
+
aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
|
51 |
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
|
52 |
+
U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
|
53 |
+
SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
|
54 |
+
biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
|
55 |
+
IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
|
56 |
+
GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
|
57 |
+
fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
|
58 |
+
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
|
59 |
+
aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
|
60 |
+
aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
|
61 |
+
kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
|
62 |
+
4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
|
63 |
+
FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
|
64 |
+
-----END CERTIFICATE-----
|
65 |
+
-----BEGIN CERTIFICATE-----
|
66 |
+
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
|
67 |
+
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
68 |
+
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
69 |
+
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
70 |
+
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
71 |
+
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
|
72 |
+
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
|
73 |
+
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
|
74 |
+
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
|
75 |
+
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
|
76 |
+
aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
|
77 |
+
nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
|
78 |
+
t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
|
79 |
+
SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
|
80 |
+
BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
|
81 |
+
rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
|
82 |
+
NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
|
83 |
+
BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
|
84 |
+
BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
|
85 |
+
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
|
86 |
+
MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
|
87 |
+
p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
|
88 |
+
5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
|
89 |
+
WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
|
90 |
+
4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
|
91 |
+
hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
|
92 |
+
-----END CERTIFICATE-----
|
93 |
+
-----BEGIN CERTIFICATE-----
|
94 |
+
MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
|
95 |
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
96 |
+
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
97 |
+
MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
98 |
+
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
99 |
+
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
100 |
+
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
101 |
+
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
102 |
+
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
103 |
+
CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
|
104 |
+
2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
|
105 |
+
2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
|
106 |
+
-----END CERTIFICATE-----
|
107 |
+
-----BEGIN CERTIFICATE-----
|
108 |
+
MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
|
109 |
+
MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
|
110 |
+
FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
|
111 |
+
MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
|
112 |
+
cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
|
113 |
+
AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
|
114 |
+
Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
|
115 |
+
0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
|
116 |
+
wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
|
117 |
+
7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
|
118 |
+
8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
|
119 |
+
BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
|
120 |
+
/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
|
121 |
+
JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
|
122 |
+
NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
|
123 |
+
6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
|
124 |
+
3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
|
125 |
+
D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
|
126 |
+
CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
|
127 |
+
3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
|
128 |
+
-----END CERTIFICATE-----
|
129 |
+
-----BEGIN CERTIFICATE-----
|
130 |
+
MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
|
131 |
+
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
|
132 |
+
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
|
133 |
+
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
|
134 |
+
NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
|
135 |
+
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
|
136 |
+
AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
|
137 |
+
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
|
138 |
+
E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
|
139 |
+
/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
|
140 |
+
DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
|
141 |
+
GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
|
142 |
+
tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
|
143 |
+
AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
|
144 |
+
FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
|
145 |
+
WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
|
146 |
+
9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
|
147 |
+
gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
|
148 |
+
2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
|
149 |
+
LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
|
150 |
+
4uJEvlz36hz1
|
151 |
+
-----END CERTIFICATE-----
|
152 |
+
-----BEGIN CERTIFICATE-----
|
153 |
+
MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
|
154 |
+
MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
|
155 |
+
c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
|
156 |
+
VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
|
157 |
+
c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
|
158 |
+
AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
|
159 |
+
WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
|
160 |
+
FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
|
161 |
+
XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
|
162 |
+
se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
|
163 |
+
KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
|
164 |
+
IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
|
165 |
+
y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
|
166 |
+
hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
|
167 |
+
QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
|
168 |
+
Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
|
169 |
+
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
|
170 |
+
HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
171 |
+
KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
|
172 |
+
dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
|
173 |
+
L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
|
174 |
+
Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
|
175 |
+
ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
|
176 |
+
T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
|
177 |
+
GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
|
178 |
+
1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
|
179 |
+
OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
|
180 |
+
6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
|
181 |
+
QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
|
182 |
+
-----END CERTIFICATE-----
|
183 |
+
-----BEGIN CERTIFICATE-----
|
184 |
+
MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
|
185 |
+
MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
|
186 |
+
c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
|
187 |
+
BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
|
188 |
+
IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
|
189 |
+
VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
|
190 |
+
cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
|
191 |
+
QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
|
192 |
+
F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
|
193 |
+
c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
|
194 |
+
mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
|
195 |
+
VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
|
196 |
+
teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
|
197 |
+
f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
|
198 |
+
Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
|
199 |
+
nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
|
200 |
+
/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
|
201 |
+
MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
|
202 |
+
9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
|
203 |
+
aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
|
204 |
+
IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
|
205 |
+
ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
|
206 |
+
uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
|
207 |
+
Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
|
208 |
+
QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
|
209 |
+
koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
|
210 |
+
ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
|
211 |
+
DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
|
212 |
+
bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
|
213 |
+
-----END CERTIFICATE-----
|
214 |
+
-----BEGIN CERTIFICATE-----
|
215 |
+
MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
|
216 |
+
MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
|
217 |
+
IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
|
218 |
+
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
|
219 |
+
R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
|
220 |
+
PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
|
221 |
+
Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
|
222 |
+
TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
|
223 |
+
5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
|
224 |
+
S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
|
225 |
+
2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
|
226 |
+
FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
|
227 |
+
EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
|
228 |
+
EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
|
229 |
+
/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
|
230 |
+
A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
|
231 |
+
abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
|
232 |
+
I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
|
233 |
+
4iIprn2DQKi6bA==
|
234 |
+
-----END CERTIFICATE-----
|
235 |
+
-----BEGIN CERTIFICATE-----
|
236 |
+
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
237 |
+
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
238 |
+
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
|
239 |
+
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
|
240 |
+
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
|
241 |
+
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
|
242 |
+
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
|
243 |
+
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
|
244 |
+
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
|
245 |
+
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
|
246 |
+
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
|
247 |
+
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
|
248 |
+
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
|
249 |
+
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
|
250 |
+
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
|
251 |
+
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
|
252 |
+
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
|
253 |
+
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
|
254 |
+
-----END CERTIFICATE-----
|
255 |
+
-----BEGIN CERTIFICATE-----
|
256 |
+
MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
|
257 |
+
MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
|
258 |
+
FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
|
259 |
+
MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
|
260 |
+
cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
|
261 |
+
AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
|
262 |
+
Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
|
263 |
+
0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
|
264 |
+
wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
|
265 |
+
7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
|
266 |
+
8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
|
267 |
+
BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
|
268 |
+
/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
|
269 |
+
JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
|
270 |
+
NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
|
271 |
+
6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
|
272 |
+
3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
|
273 |
+
D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
|
274 |
+
CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
|
275 |
+
3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
|
276 |
+
-----END CERTIFICATE-----
|
277 |
+
-----BEGIN CERTIFICATE-----
|
278 |
+
MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
|
279 |
+
MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
|
280 |
+
IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
|
281 |
+
BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
|
282 |
+
MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
|
283 |
+
d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
|
284 |
+
YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
|
285 |
+
dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
|
286 |
+
BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
|
287 |
+
papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
|
288 |
+
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
|
289 |
+
DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
|
290 |
+
KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
|
291 |
+
XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
|
292 |
+
-----END CERTIFICATE-----
|
293 |
+
-----BEGIN CERTIFICATE-----
|
294 |
+
MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
|
295 |
+
qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
|
296 |
+
Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
|
297 |
+
MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
|
298 |
+
BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
|
299 |
+
NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
|
300 |
+
LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
|
301 |
+
A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
|
302 |
+
IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
|
303 |
+
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
|
304 |
+
W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
|
305 |
+
3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
|
306 |
+
6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
|
307 |
+
Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
|
308 |
+
NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
|
309 |
+
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
|
310 |
+
r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
|
311 |
+
DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
|
312 |
+
YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
|
313 |
+
xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
|
314 |
+
/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
|
315 |
+
LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
|
316 |
+
jVaMaA==
|
317 |
+
-----END CERTIFICATE-----
|
318 |
+
-----BEGIN CERTIFICATE-----
|
319 |
+
MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
|
320 |
+
MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
|
321 |
+
IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
|
322 |
+
BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
|
323 |
+
MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
|
324 |
+
d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
|
325 |
+
YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
|
326 |
+
dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
|
327 |
+
BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
|
328 |
+
papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
|
329 |
+
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
|
330 |
+
DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
|
331 |
+
KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
|
332 |
+
XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
|
333 |
+
-----END CERTIFICATE-----
|
334 |
+
-----BEGIN CERTIFICATE-----
|
335 |
+
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
|
336 |
+
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
|
337 |
+
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
|
338 |
+
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
|
339 |
+
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
|
340 |
+
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
|
341 |
+
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
|
342 |
+
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
|
343 |
+
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
|
344 |
+
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
|
345 |
+
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
|
346 |
+
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
|
347 |
+
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
|
348 |
+
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
|
349 |
+
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
|
350 |
+
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
|
351 |
+
-----END CERTIFICATE-----
|
lib/ssl/sandbox_braintreegateway_com.ca.crt
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com
|
2 |
+
-----BEGIN CERTIFICATE-----
|
3 |
+
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
|
4 |
+
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
|
5 |
+
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
|
6 |
+
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
|
7 |
+
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
|
8 |
+
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
|
9 |
+
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
|
10 |
+
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
|
11 |
+
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
|
12 |
+
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
|
13 |
+
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
|
14 |
+
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
|
15 |
+
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
|
16 |
+
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
|
17 |
+
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
|
18 |
+
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
|
19 |
+
-----END CERTIFICATE-----
|
20 |
+
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Gene_Braintree</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/mit-license.php">MIT License</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Connect your Magento store to Braintree to accept Credit Cards &amp; PayPal using V.Zero SDK</summary>
|
10 |
+
<description>Connect your Magento store to Braintree to accept Credit Cards &amp; PayPal using V.Zero SDK</description>
|
11 |
+
<notes>Connect your Magento store to Braintree to accept Credit Cards &amp; PayPal using V.Zero SDK</notes>
|
12 |
+
<authors><author><name>Dave Macaulay</name><user>dave</user><email>magento@gene.co.uk</email></author></authors>
|
13 |
+
<date>2015-04-20</date>
|
14 |
+
<time>14:05:41</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="Gene"><dir name="Braintree"><dir name="Block"><dir name="Adminhtml"><dir name="Report"><dir name="Transactions"><file name="Grid.php" hash="32b32086548f62ae4aca4baf456b9ed2"/><file name="Search.php" hash="81d57c3744530f36c37782ce9d0f3a70"/></dir><file name="Transactions.php" hash="7afe45b49353e52b432aa0392d76a08e"/></dir><dir name="System"><dir name="Config"><dir name="Braintree"><file name="Config.php" hash="eaaf6c74be4233a315d5aa5932f7c9ca"/><file name="Currency.php" hash="9ffa8a2ded53be75e88a60a024883b07"/><file name="Moduleversion.php" hash="fe3836bde24bb31c4c4585f2cd2f20ed"/><file name="Version.php" hash="ce58278a4faf965301cc2d8b2da4483c"/></dir></dir></dir></dir><dir name="Cart"><file name="Totals.php" hash="a03c441e8143896f92d02931a809f666"/></dir><dir name="Creditcard"><file name="Info.php" hash="40aa92bed04bd3744048befca2a0217a"/><file name="Threedsecure.php" hash="8eae09e8167e787f24eb80bc7ad7cd4a"/></dir><file name="Creditcard.php" hash="989678324ff3fcddcc99cbe4613019fa"/><file name="Js.php" hash="d1b2dbd2ba187100ecbbedefc633b845"/><dir name="Paypal"><file name="Info.php" hash="a0206fad8b91aa382c3ac16b9651c723"/></dir><file name="Paypal.php" hash="36294a461378cceee66e99d45753c6e1"/><file name="Saved.php" hash="74ed8e70a404a814b94f21f88c1ca737"/></dir><dir name="Helper"><file name="Data.php" hash="a5b64dd6760e881b1823adfaeb7c1501"/></dir><dir name="Model"><file name="Debug.php" hash="f3360f71e2346881f93424792ed9f209"/><file name="Observer.php" hash="176b48ac3b74bfaa3c28f4126093b49b"/><dir name="Paymentmethod"><file name="Abstract.php" hash="4043a0ac548fe0ec9acbc2dd0c57dfb4"/><file name="Creditcard.php" hash="822df144f2731ef4ceeade79f899e570"/><file name="Paypal.php" hash="445bb04b3b1d5d41383962ec8ef9daa3"/></dir><file name="Saved.php" hash="3b235b454a3692d1c3d5343e2a1c91e9"/><dir name="Source"><file name="Cctype.php" hash="d76aa6c3a4bd798e3a47695f579d21d4"/><dir name="Creditcard"><file name="CaptureAction.php" hash="6444cfc430de44f06e85bd9c8b80d77b"/><file name="PaymentAction.php" hash="a2f3f3d36a98df4d12f76b6ab77f9c47"/></dir><file name="Environment.php" hash="02567d2ddba74d06ac000b4ddb12723a"/><dir name="Paypal"><file name="Locale.php" hash="8988ca77f9c2aa2d19ff0b614a4b7621"/><file name="Paymenttype.php" hash="fe1fe4ee89d5b7a87c7c28716bb2f1cb"/></dir></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Currency.php" hash="f0cca96917d3c4c2bc05aa255544f25a"/></dir></dir></dir><dir name="Wrapper"><file name="Braintree.php" hash="aa38b6ecd7fa18c75d1bf5571cdf60fc"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="BraintreeController.php" hash="7c621fa1548c04e24bb1136bcbbe1d72"/></dir><file name="CheckoutController.php" hash="7494f5fa81cbae80778fac80fa577101"/><file name="SavedController.php" hash="036e97703c853a5bae064dd7cf5030a8"/></dir><dir name="etc"><file name="adminhtml.xml" hash="c9c940beffa0ec19e4a1499a66f7fd12"/><file name="config.xml" hash="52add3f1ba81840e9771d756b7137d22"/><file name="system.xml" hash="077114993f5d60f16e8d33221cbd19ff"/></dir><dir name="sql"><dir name="gene_braintree_setup"><file name="install-0.1.0.php" hash="7ef62b7c19b9da5990974da6edb3e77c"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><dir name="gene"><file name="braintree.xml" hash="1ded19331e4656bd31d052eb729ff7c2"/></dir></dir><dir name="template"><dir name="gene"><dir name="braintree"><dir name="creditcard"><file name="info.phtml" hash="2ae1e397b3a633dd305bc26c7b9c1065"/><file name="threedsecure.phtml" hash="ee8ad689afde041c39dd92ffa5274883"/></dir><file name="creditcard.phtml" hash="a083837c8b7d32b61336f891c5a87cb8"/><dir name="customer"><file name="methods.phtml" hash="eb5e2d8f4a0f419fcf720c12062f808a"/><file name="saved.phtml" hash="691162b89ed085599f76072226ca2307"/></dir><dir name="js"><file name="amasty.phtml" hash="652f7d6b1c9dfe6249b29ca8ee8abf82"/><file name="data.phtml" hash="7c77e2c13c9037ab993b7c7f8aa72d98"/><file name="default.phtml" hash="4fde57aa847f06bc02feaaf9097b1f57"/><file name="idev.phtml" hash="9328346d501ca6ab91451d5a99fdc287"/><file name="setup.phtml" hash="86a6da43f073b5fc75ce170a50af3bcd"/></dir><dir name="paypal"><file name="info.phtml" hash="5149b273730121e4dec3c3179820f747"/></dir><file name="paypal.phtml" hash="3c579ad7ba3290c15fcce027cdd66d16"/></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="gene"><file name="braintree.xml" hash="1995e85eb47b909120ce8b9b537bf5db"/></dir></dir><dir name="template"><dir name="gene"><dir name="braintree"><dir name="creditcard"><file name="info.phtml" hash="3c5f033eb99ab8d78517ae5eb45a3a1a"/></dir><file name="creditcard.phtml" hash="0c6b7806732c336ead14fab596f1b923"/><file name="js.phtml" hash="9d51d9d573ada5f3222e29e4b9b7aaa1"/><dir name="paypal"><file name="info.phtml" hash="53fae03530369f101f5eaed49508a1ee"/></dir><dir name="transactions"><file name="index.phtml" hash="1791b6393f319616dd79c0b46e391847"/><file name="search.phtml" hash="1682ce6200681681f0ce3c848e2e6694"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Gene_Braintree.xml" hash="8c0ffda8566dca2f0b98a999921e3e55"/></dir></target><target name="mageweb"><dir name="js"><dir name="gene"><dir name="braintree"><file name="braintree.js" hash="4a074b2952d6e3c0052f85442b284abc"/><file name="vzero.js" hash="7e9bf97aee5e7bfe9c2d465b0609d238"/></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="images"><dir name="gene"><dir name="braintree"><file name="AE.png" hash="6b6f405105413b0723a62ee498f88bf6"/><file name="DI.png" hash="d8e3c3022dda9e723f466b8976ae428f"/><file name="JCB.png" hash="3aa9a71ed8a1d6610bbe0dfe2040e29e"/><file name="MC.png" hash="1fcd14928245139962b72f9368bdbe32"/><file name="ME.png" hash="b9389913c47b9546a67f907fcca73706"/><file name="PP.png" hash="b4946bccba574e86c9716a4986e21c36"/><file name="VI.png" hash="c9f74d1d54e61ab2c748f45a4bdface0"/><file name="card.png" hash="66e16f8c573fad93bb0d62258dce28bb"/><file name=".DS_Store" hash="194577a7e20bdcc7afbb718f502c134c"/></dir></dir></dir></dir></dir></dir></target><target name="magelib"><dir name="Braintree"><file name="AddOn.php" hash="07bc690cf426276dfdd802c49cfd72a3"/><file name="AddOnGateway.php" hash="ed9a94155c1c13ba37910fd48bdad40a"/><file name="Address.php" hash="1d4e7f964ed208a381b352d21fc370b8"/><file name="AddressGateway.php" hash="11716dc4ede8b7455197d08b88c91568"/><file name="ApplePayCard.php" hash="6fdbe99722514408f613c417e0e48711"/><file name="ClientToken.php" hash="f606f4bbafaea470333290be52b0030d"/><file name="ClientTokenGateway.php" hash="ede93fa63f0e96d296f315180f5ff1ad"/><file name="CoinbaseAccount.php" hash="7a4992ed13c26ad3785cf7d3455ef5fb"/><file name="Collection.php" hash="0e7d31ffcbd9780fb554186bd2c194b0"/><file name="Configuration.php" hash="6414dae20a80d926c28bd681bb535934"/><file name="CreditCard.php" hash="cf0aab2bcdcc7c231ccedc05a0f853e4"/><file name="CreditCardGateway.php" hash="3c5c3d9cee27da71e338b51d42b685ee"/><file name="CreditCardVerification.php" hash="48d6ea546914278f4bea2fefb75e7836"/><file name="CreditCardVerificationGateway.php" hash="e020dd1c26cd8c3bd7eb55eed2f72346"/><file name="CreditCardVerificationSearch.php" hash="baa6ed22471ea1f142a4195d1e36f89a"/><file name="Customer.php" hash="69d834344b93277dbeadb4ee6a881a60"/><file name="CustomerGateway.php" hash="bde59d4c6d7418fcbd87d4484384705b"/><file name="CustomerSearch.php" hash="8aacc83dac341cd9afec5a3deab17593"/><file name="Descriptor.php" hash="3f5db5e817280ce7f2fa18a205281ad9"/><file name="Digest.php" hash="9d12d067770f55b123b8498fce4478fa"/><file name="Disbursement.php" hash="589534043e466d17fede916fd7986edc"/><file name="DisbursementDetails.php" hash="ae632207d0982e288a83aed401c880d9"/><file name="Discount.php" hash="763b3f9cde0ff3af3e8795cac4097595"/><file name="DiscountGateway.php" hash="42ca6f2f11074ec18eecd1506996a393"/><dir name="Dispute"><file name="TransactionDetails.php" hash="7fdea673a1295055508f42286ad57f4e"/></dir><file name="Dispute.php" hash="2ee0f4a77b7cfec4763b55627a57e348"/><file name="EqualityNode.php" hash="cfd6aa184186233b8d6d1ec0f0e79298"/><dir name="Error"><file name="Codes.php" hash="d0d1007255af20889a4874d028ebeab2"/><file name="ErrorCollection.php" hash="e28d638db56524f5bf3609fa725e6d55"/><file name="Validation.php" hash="bf4e2198300019c52ba56f16269d66ce"/><file name="ValidationErrorCollection.php" hash="9ef25d0126a0b4f6951da5334ae6f0dc"/></dir><dir name="Exception"><file name="Authentication.php" hash="f9e13654988452cca2ac5228a80adae4"/><file name="Authorization.php" hash="5f8c017c6e9fd79a556dade8e15a72e8"/><file name="Configuration.php" hash="b50f67e8ea36cff0d9f6ad718126c6fc"/><file name="DownForMaintenance.php" hash="7fd30b1f8976ed7e38b7e9fae5c20f03"/><file name="ForgedQueryString.php" hash="6884dbae1e86767834b77c821df2db62"/><file name="InvalidSignature.php" hash="b83f5b16735cb3a8e0a8111c4f32711e"/><file name="NotFound.php" hash="f832f771d20b381c2780eb2a572b9f44"/><file name="SSLCaFileNotFound.php" hash="e927c7307bf1761814dc8a755238070d"/><file name="SSLCertificate.php" hash="d509b6a6206bd7c5563ac142dfe3801f"/><file name="ServerError.php" hash="b4645290229ab228a257047d08ef63d7"/><file name="Unexpected.php" hash="01ea2800fb91995ec2a15aee5024611e"/><file name="UpgradeRequired.php" hash="7f40b174df891cc3b3e206d1be884a58"/><file name="ValidationsFailed.php" hash="cd2d30c69911f81b55279c3d6bf88c61"/></dir><file name="Exception.php" hash="f14c94bf67206184eb3e4e7aeb4a608a"/><file name="Gateway.php" hash="8b214a63ed50539e75031caff78d4560"/><file name="Http.php" hash="5f6a9990a14684c82b6952937889412b"/><file name="Instance.php" hash="f0603b3f9213b53687e079c5621ac8f3"/><file name="IsNode.php" hash="e4b1f7bbfcbd24b1d08b97f94df592be"/><file name="KeyValueNode.php" hash="255595ec01a16906dd0c49faf67d9efb"/><dir name="MerchantAccount"><file name="AddressDetails.php" hash="1d265d864a884ebcf2504f55207cc0dd"/><file name="BusinessDetails.php" hash="c9ae627c4a4b526c2ecb0c07d70b3017"/><file name="FundingDetails.php" hash="7368f653fcbcc3d87924447b1763e616"/><file name="IndividualDetails.php" hash="68daf00759335cde82f176f0844e0d9b"/></dir><file name="MerchantAccount.php" hash="489844cfd91dcc6a53024af97b85f3c7"/><file name="MerchantAccountGateway.php" hash="6a9033758b8c02501fd835a96fc385b7"/><file name="Modification.php" hash="fcce6784af2e658affe4a67ca75d8230"/><file name="MultipleValueNode.php" hash="92700fa03011eaa9561010b3a160449c"/><file name="MultipleValueOrTextNode.php" hash="ef06bac18e2bc40974bdc0bcb854890f"/><file name="PartialMatchNode.php" hash="370c7e0ab8a445cfeef6b19ef1755f4d"/><file name="PartnerMerchant.php" hash="20c87322d040eac1abcdf12b8838ec1c"/><file name="PayPalAccount.php" hash="1bbe86a33bbf3e3620364ba0c2e9b6fe"/><file name="PayPalAccountGateway.php" hash="bdf94548085765927368c49bcf028f47"/><file name="PaymentInstrumentType.php" hash="84e2d2fcfe45cf7cf188dc46f302fac8"/><file name="PaymentMethod.php" hash="8aca88278367fcbd5404a0abae848a45"/><file name="PaymentMethodGateway.php" hash="ed81d66dcb097021c4f6518b9ea5e5cf"/><file name="PaymentMethodNonce.php" hash="a72e8ed6506327cdac92d8b082e4dd74"/><file name="PaymentMethodNonceGateway.php" hash="e8ee61d15b73bd2ef9efef8a6b5f4132"/><file name="Plan.php" hash="f73f24fcc57cfeb2e6f0e6312e531073"/><file name="PlanGateway.php" hash="8392fc6b714b30d16fe0308a1e81db4f"/><file name="RangeNode.php" hash="4ad9a92547423b3d54d69097114c3daf"/><file name="ResourceCollection.php" hash="8f437cb5014148c0e2f6049347ae795c"/><dir name="Result"><file name="CreditCardVerification.php" hash="27b965f1e197b0392879e24cccf6dd9c"/><file name="Error.php" hash="81b616e25f182c0c571ad4e9e6fbc611"/><file name="Successful.php" hash="56c6f9a3e5996d18e01a8d382cc03cde"/></dir><file name="RiskData.php" hash="dd74658f351fe8af26cee3016a076fb9"/><file name="SettlementBatchSummary.php" hash="0dcc2b5dd7071d9037cf5970fafe8668"/><file name="SettlementBatchSummaryGateway.php" hash="4ec1a7a1c8875693123430aa51410b22"/><file name="SignatureService.php" hash="4b78d3e5897e715dcc877c5f65b3cfae"/><dir name="Subscription"><file name="StatusDetails.php" hash="29e375f02150bfd7147591f0eb27cb4f"/></dir><file name="Subscription.php" hash="96db82b5b67a72d4287d79b7c691b3d7"/><file name="SubscriptionGateway.php" hash="34118ee95b83d8904a47b388cbb8cfea"/><file name="SubscriptionSearch.php" hash="1874ebe5cb42d7d2836617810cced1af"/><dir name="Test"><file name="CreditCardNumbers.php" hash="676a9100354eb679e7ca1e0f0d67293f"/><file name="MerchantAccount.php" hash="612e7e30cca364c0d14cbff3b54ebf3f"/><file name="Nonces.php" hash="89bb29ef4552037973fe04d344f657ef"/><file name="TransactionAmounts.php" hash="ed9bf1f57d871542c32d11de9e031f05"/><file name="VenmoSdk.php" hash="6ce94deccd1f968596011487c7e69cc7"/></dir><file name="TextNode.php" hash="94c95ec9645de57acace2179fef7fb43"/><dir name="Transaction"><file name="AddressDetails.php" hash="ff52a4a48248085b7ea92e992160e413"/><file name="ApplePayCardDetails.php" hash="c4dd87cd46fe7269e1bd51c867adf7cb"/><file name="CoinbaseDetails.php" hash="d19a625f8de98698b8277c25660358f0"/><file name="CreditCardDetails.php" hash="aac5eb1f5804d4f979b9c71f7b98cb36"/><file name="CustomerDetails.php" hash="e137895c646127312be44292c84a2d81"/><file name="PayPalDetails.php" hash="ede299e376bce7714838d79ca3d40842"/><file name="StatusDetails.php" hash="7c6e719c51bf13bdfd07615030100ac6"/><file name="SubscriptionDetails.php" hash="1cf1f511d1545a2e27b8d3f4bee800ca"/></dir><file name="Transaction.php" hash="9970a0fa9d6af3e543703426da99a3c4"/><file name="TransactionGateway.php" hash="37500b8a181a18375c171d4a5a4938c6"/><file name="TransactionSearch.php" hash="41dd086066fa57582161032249b3d8ee"/><file name="TransparentRedirect.php" hash="154c9850be5175a5cd1b35bdf78ae939"/><file name="TransparentRedirectGateway.php" hash="89f002df5a2abafcaa9676a3e2935c75"/><file name="UnknownPaymentMethod.php" hash="811394ea4bee98a651dc5e1cba8223da"/><file name="Util.php" hash="2cf47c3acd49da4a6c2b0a9a55701d7b"/><file name="Version.php" hash="1ebf13fcec95da846f917f74e030714b"/><file name="WebhookNotification.php" hash="f58be59156e5728f491da4235a58e994"/><file name="WebhookTesting.php" hash="c40311458bb64e37b4c08eb88df37805"/><dir name="Xml"><file name="Generator.php" hash="f82af40e5759c3d46909f3dec2498d02"/><file name="Parser.php" hash="4e6df3327a04915715333460733df93c"/></dir><file name="Xml.php" hash="dc69e05bea21e3d1185d45d53e4747db"/></dir><dir name="."><file name="Braintree.php" hash="ee3e665877882e5b5076ff51dc8111bd"/></dir><dir name="ssl"><file name="api_braintreegateway_com.ca.crt" hash="04beb23c767547e980c76eb68c7eab15"/><file name="sandbox_braintreegateway_com.ca.crt" hash="f1b529883c7c2cbb4251658f5da7b4c9"/></dir></target><target name="magelocale"><dir><dir name="en_US"><file name="Gene_Braintree.csv" hash="00ae6dc359bc0d9c48bfc90a865232a3"/></dir></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.2.1</min><max>6.0.0</max></php><package><name/><channel>connect.magentocommerce.com/core</channel><min/><max/></package></required></dependencies>
|
18 |
+
</package>
|
skin/frontend/base/default/images/gene/braintree/.DS_Store
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/AE.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/DI.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/JCB.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/MC.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/ME.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/PP.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/VI.png
ADDED
Binary file
|
skin/frontend/base/default/images/gene/braintree/card.png
ADDED
Binary file
|