Easily integrate a CC payment form with Braintree's API into Yii.
Version 1.2 - Small update just to update to Braintree's newest version of API (2.22.2)
Version 1.1 - I have added the ability to save Customers, Credit Cards and Addresses in the Vault. See change log for more info.
I plan on adding more functionality like setting up Recurring Payments.
Requirements ¶
Yii 1.1 or + Requires PHP version 5.2 or higher and the PHP cURL extension (Braintree Requirements)
A sandbox or production account from BrainTree Payment Gateway, need following api acount info:
- merchant_id
- public_key
- private_key
- Client-Side Encryption Key
Installation ¶
Download the extension here or from Repo below and extract to 'protected/extensions/BraintreeApi'. Modify your configuration file and add fields to the param array with the appropriate info:
// application-level parameters that can be accessed
'params'=>array(
// this is used in contact page
'adminEmail'=>'your@email.com',
'braintreeapi' => array(
'class' => 'ext.BraintreeApi.BraintreeApi',
'environment' => 'sandbox', //'sandbox' or 'production'
'merchant_id' => '',
'public_key' => '',
'private_key' => '',
'clientside_key' => '',
),
),
Usage ¶
On your controller action import the extension and create a new instance of BraintreeApi and pass it to your form. You can then use the Widget to add all the fields to your form easily if you want.
Any Controller (Just an example):
public function actionPayment() {
$model = User::model()->findByPk(Yii::app()->user->id);
Yii::import('ext.BraintreeApi.models.BraintreeCCForm');
$payment = new BraintreeCCForm('charge'); //also option for 'customer', 'address', and 'creditcard'
if(isset($_POST['BraintreeCCForm'])) {
$payment->setAttributes($_POST['BraintreeCCForm']);
//$payment->customerId = '5534438'; //needed for 'address' and 'creditcard' scenarios
if($payment->validate()) {
$result = $payment->send();
if($result) {
//Success
}
}
}
$this->render('payment',array('model'=>$model,'payment'=>$payment));
}
Inside a View:
The fields
array in the widget lets you specify what fields you want to show up on the form. If you remove it completely it will default to showing just credit card number, cvv, and expiration month/year.
//start $form widget
$this->widget('ext.BraintreeApi.widgets.CCForm', array(
'form' => $form,
'form_id' => 'payment-form', //Now optional as can be retrieved in widget from $form
'model' => $payment,
'values' => $payment->attributes, //Now optional as can be retrieved in widget from $payment
//'type' => 'customer', //can use this instead of fields array below, options are 'customer', 'creditcard', 'charge_min', 'address'
'fields' => array(
'amount',
'orderId',
'creditCard' => array('number','cvv','month','year','name'),
'merchantAccountId',
'customer' => array('firstName','lastName','company','phone','fax','website','email'),
'billing' => array('firstName','lastName','company','streetAddress','extendedAddress','locality','region','postalCode','countryCodeAlpha2'),
'shipping' => array('firstName','lastName','company','streetAddress','extendedAddress','locality','region','postalCode','countryCodeAlpha2'),
),
));
Resources ¶
Change Log ¶
Version 1.2
- Updated to version 2.22.2 of Braintree's PHP API code
Version 1.1
- Created a new model BraintreeCCForm that extends CFormModel for managing form input
- Added default types for widget.
- Reduced required inputs for widget
- $this->values can be pulled from $this->model
- $this->form_id can be pulled from $this->form
- Added option to save Customers, Credit Cards and Addresses in Vault
- Added option to submitforsettlement and storetovault on singleCharge
Anyone?
Anyone using this? Any comments/suggestions? Anyone interested in the recurring payments functionality? If so I will add it, if no one is really using it I'll hold off and work on other stuff.
Not currently using braintree but...
I am working on a project where payments is very important, and am planning in implementing braintree/venmo in the future, so a robust payment extension for their services would be very helpful :)
Who knows what will happen to their API now that they're owned by PayPal though!
Recurring payments
I will definitely be using this, specifically I'd love to be able to use recurring payments and the Marketplace functionality (https://www.braintreepayments.com/marketplace).
Recurring Payments
Thanks for creating this wonderful package, I could make use of singleCharge feature. Could you pl. help implementing recurring payments. I am seeing the library files but not the implementation part.
Thanks Again..
Deepti
Recurring Payments
I haven't had a chance to play with the recurring payments yet. If I get a chance I will update this extension to include it.
Need more definition of the form widget!
What is the value of $form and how is it set?
$form definition
$form is simply a form widget, for example:
$form=$this->beginWidget('CActiveForm', array( 'id'=>'my-form', 'enableAjaxValidation'=>false, ));
Can't get payment to process...
I have the form working, comes up and I enter the data in my sandbox:
Name on card: Ji Wu
CC#: 4111111111111111
CV: 111
M/Y: 11/14
Customer info: ...
Back in actionPayment$payment I get the customer info but not the credit card info. $payment->validate() kicks out the transaction because: "Cannot determine payment method." I've been through the braintree code to figure out what it's doing with CC info and I've not found it yet.
Where to go from here?
Payment Processing Issue:
This example relies on a user object:
$model = User::model()->findByPk(Yii::app()->user->id);
That user object is defined specifically to have the BraintreeApi object within it:
CCForm.php:86: var braintree = Braintree.create('{$this->model->BraintreeApi->clientside_key}');
So you must have the "model" which does not need to be the application User model (and probably shouldn't be IMHO--my app defines $User as a database table that does not and should not contain this info) defined specifically with the BraintreeApi object defined in a way that is not required for it to function outside of this example.
I'm still figuring this out but would appreciate advice.
Had to make changes to get this working
1) Changed main.php:
'params'=>array( // this is used in contact page 'adminEmail'=>'msigler9@gmail.com', 'braintreeapi'=>array( // INSERT THE BRAINTREE CONFIG VALUES HERE! 'environment' => '', 'merchant_id' => '', 'public_key' => '', 'private_key' => '', 'clientside_key' => '' ) )
had to add code to Configuration.php:
public static function reset() { self::$_cache = array ( 'environment' => '', 'merchantId' => '', 'publicKey' => '', 'privateKey' => '', 'clientsideKey' =>'' ); } public static function clientsideKey($value = null) { return self::setOrGet(__FUNCTION__, $value); }
Added code to Braintree.api:
public function __construct() { $this->environment = Yii::app()->params['braintreeapi']['environment']; $this->merchant_id = Yii::app()->params['braintreeapi']['merchant_id']; $this->public_key = Yii::app()->params['braintreeapi']['public_key']; $this->private_key = Yii::app()->params['braintreeapi']['private_key']; $this->clientside_key = Yii::app()->params['braintreeapi']['clientside_key']; require('lib/Braintree.php'); Braintree_Configuration::environment($this->environment); Braintree_Configuration::merchantId($this->merchant_id); Braintree_Configuration::publicKey($this->public_key); Braintree_Configuration::privateKey($this->private_key); Braintree_Configuration::clientsideKey($this->clientside_key); }
Then modified the method above like this:
public function actionPayment() {
//$model = User::model()->findByPk(Yii::app()->user->id); Yii::import('ext.BraintreeApi.models.BraintreeCCForm'); $payment = new BraintreeCCForm('charge'); //also option for 'customer', 'address', and 'creditcard' if(isset($_POST['BraintreeCCForm'])) { $payment->setAttributes($_POST['BraintreeCCForm']); //$payment->customerId = '5534438'; //needed for 'address' and 'creditcard' scenarios if($payment->validate()) { $result = $payment->send(); if($result) { //Success } } } **$this->render('payment',array('model'=>$payment,'payment'=>$payment));** **//yikes two different variables required for the same object! One in form the other in js** }
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.