mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-18 00:53:10 +01:00
Add Braintree/PayPal support
This commit is contained in:
parent
cf98c37f40
commit
0fc44962d4
@ -110,13 +110,25 @@ class AccountGatewayController extends BaseController
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type == PAYMENT_TYPE_STRIPE && $account->getGatewayByType(PAYMENT_TYPE_CREDIT_CARD)) {
|
||||
// Another gateway is already handling credit card payments
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type == PAYMENT_TYPE_DIRECT_DEBIT && $stripeGateway = $account->getGatewayByType(PAYMENT_TYPE_STRIPE)) {
|
||||
if (!empty($stripeGateway->getConfig()->enableAch)) {
|
||||
if (!empty($stripeGateway->getAchEnabled())) {
|
||||
// Stripe is already handling ACH payments
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type == PAYMENT_TYPE_PAYPAL && $braintreeGateway = $account->getGatewayConfig(GATEWAY_BRAINTREE)) {
|
||||
if (!empty($braintreeGateway->getPayPalEnabled())) {
|
||||
// PayPal is already enabled
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$paymentTypes[$type] = $type == PAYMENT_TYPE_CREDIT_CARD ? trans('texts.other_providers'): trans('texts.'.strtolower($type));
|
||||
|
||||
if ($type == PAYMENT_TYPE_BITCOIN) {
|
||||
@ -300,6 +312,10 @@ class AccountGatewayController extends BaseController
|
||||
$config->enableAch = boolval(Input::get('enable_ach'));
|
||||
}
|
||||
|
||||
if ($gatewayId == GATEWAY_BRAINTREE) {
|
||||
$config->enablePayPal = boolval(Input::get('enable_paypal'));
|
||||
}
|
||||
|
||||
$cardCount = 0;
|
||||
if ($creditcards) {
|
||||
foreach ($creditcards as $card => $value) {
|
||||
|
@ -152,63 +152,83 @@ class PaymentController extends BaseController
|
||||
$account->account_gateways[0]->getPaymentType();
|
||||
}
|
||||
|
||||
if ($paymentType == PAYMENT_TYPE_TOKEN) {
|
||||
$useToken = true;
|
||||
$accountGateway = $invoice->client->account->getTokenGateway();
|
||||
$paymentType = $accountGateway->getPaymentType();
|
||||
} else {
|
||||
$accountGateway = $invoice->client->account->getGatewayByType($paymentType);
|
||||
}
|
||||
$data = array();
|
||||
|
||||
Session::put($invitation->id . 'payment_type', $paymentType);
|
||||
|
||||
$gateway = $accountGateway->gateway;
|
||||
|
||||
$acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();
|
||||
|
||||
$isOffsite = ($paymentType != PAYMENT_TYPE_CREDIT_CARD && $accountGateway->getPaymentType() != PAYMENT_TYPE_STRIPE)
|
||||
|| $gateway->id == GATEWAY_EWAY
|
||||
|| $gateway->id == GATEWAY_TWO_CHECKOUT
|
||||
|| $gateway->id == GATEWAY_PAYFAST
|
||||
|| $gateway->id == GATEWAY_MOLLIE;
|
||||
|
||||
// Handle offsite payments
|
||||
if ($useToken || $isOffsite) {
|
||||
if (Session::has('error')) {
|
||||
Session::reflash();
|
||||
return Redirect::to('view/'.$invitationKey);
|
||||
if ($paymentType != PAYMENT_TYPE_BRAINTREE_PAYPAL) {
|
||||
if ($paymentType == PAYMENT_TYPE_TOKEN) {
|
||||
$useToken = true;
|
||||
$accountGateway = $invoice->client->account->getTokenGateway();
|
||||
$paymentType = $accountGateway->getPaymentType();
|
||||
} else {
|
||||
return self::do_payment($invitationKey, false, $useToken, $sourceId);
|
||||
$accountGateway = $invoice->client->account->getGatewayByType($paymentType);
|
||||
}
|
||||
|
||||
Session::put($invitation->id . 'payment_type', $paymentType);
|
||||
|
||||
$gateway = $accountGateway->gateway;
|
||||
|
||||
$acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();
|
||||
|
||||
$isOffsite = ($paymentType != PAYMENT_TYPE_CREDIT_CARD && $accountGateway->getPaymentType() != PAYMENT_TYPE_STRIPE)
|
||||
|| $gateway->id == GATEWAY_EWAY
|
||||
|| $gateway->id == GATEWAY_TWO_CHECKOUT
|
||||
|| $gateway->id == GATEWAY_PAYFAST
|
||||
|| $gateway->id == GATEWAY_MOLLIE;
|
||||
|
||||
// Handle offsite payments
|
||||
if ($useToken || $isOffsite) {
|
||||
if (Session::has('error')) {
|
||||
Session::reflash();
|
||||
return Redirect::to('view/' . $invitationKey);
|
||||
} else {
|
||||
return self::do_payment($invitationKey, false, $useToken, $sourceId);
|
||||
}
|
||||
}
|
||||
|
||||
$data += [
|
||||
'accountGateway' => $accountGateway,
|
||||
'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
|
||||
'gateway' => $gateway,
|
||||
'showAddress' => $accountGateway->show_address,
|
||||
];
|
||||
|
||||
if ($paymentType == PAYMENT_TYPE_STRIPE_ACH) {
|
||||
$data['currencies'] = Cache::get('currencies');
|
||||
}
|
||||
|
||||
if ($gateway->id == GATEWAY_BRAINTREE) {
|
||||
$data['braintreeClientToken'] = $this->paymentService->getBraintreeClientToken($account);
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($deviceData = Input::get('details')) {
|
||||
Session::put($invitation->id . 'device_data', $deviceData);
|
||||
}
|
||||
|
||||
Session::put($invitation->id . 'payment_type', PAYMENT_TYPE_BRAINTREE_PAYPAL);
|
||||
$paypalDetails = json_decode(Input::get('details'));
|
||||
if (!$sourceId || !$paypalDetails) {
|
||||
return Redirect::to('view/'.$invitationKey);
|
||||
}
|
||||
$data['paypalDetails'] = $paypalDetails;
|
||||
}
|
||||
|
||||
$data = [
|
||||
$data += [
|
||||
'showBreadcrumbs' => false,
|
||||
'url' => 'payment/'.$invitationKey,
|
||||
'amount' => $invoice->getRequestedAmount(),
|
||||
'invoiceNumber' => $invoice->invoice_number,
|
||||
'client' => $client,
|
||||
'contact' => $invitation->contact,
|
||||
'gateway' => $gateway,
|
||||
'accountGateway' => $accountGateway,
|
||||
'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
|
||||
'paymentType' => $paymentType,
|
||||
'countries' => Cache::get('countries'),
|
||||
'currencyId' => $client->getCurrencyId(),
|
||||
'currencyCode' => $client->currency ? $client->currency->code : ($account->currency ? $account->currency->code : 'USD'),
|
||||
'account' => $client->account,
|
||||
'sourceId' => $sourceId,
|
||||
'clientFontUrl' => $client->account->getFontsUrl(),
|
||||
'showAddress' => $accountGateway->show_address,
|
||||
];
|
||||
|
||||
if ($paymentType == PAYMENT_TYPE_STRIPE_ACH) {
|
||||
$data['currencies'] = Cache::get('currencies');
|
||||
}
|
||||
|
||||
if ($gateway->id == GATEWAY_BRAINTREE) {
|
||||
$data['braintreeClientToken'] = $this->paymentService->getBraintreeClientToken($account);
|
||||
}
|
||||
|
||||
return View::make('payments.add_paymentmethod', $data);
|
||||
}
|
||||
|
||||
@ -381,7 +401,6 @@ class PaymentController extends BaseController
|
||||
$paymentType = Session::get($invitation->id . 'payment_type');
|
||||
$accountGateway = $account->getGatewayByType($paymentType);
|
||||
|
||||
|
||||
$rules = [
|
||||
'first_name' => 'required',
|
||||
'last_name' => 'required',
|
||||
@ -399,7 +418,9 @@ class PaymentController extends BaseController
|
||||
);
|
||||
}
|
||||
|
||||
if ($accountGateway->show_address) {
|
||||
$requireAddress = $accountGateway->show_address && $paymentType != PAYMENT_TYPE_STRIPE_ACH && $paymentType != PAYMENT_TYPE_BRAINTREE_PAYPAL;
|
||||
|
||||
if ($requireAddress) {
|
||||
$rules = array_merge($rules, [
|
||||
'address1' => 'required',
|
||||
'city' => 'required',
|
||||
@ -418,7 +439,7 @@ class PaymentController extends BaseController
|
||||
->withInput(Request::except('cvv'));
|
||||
}
|
||||
|
||||
if ($accountGateway->update_address) {
|
||||
if ($requireAddress && $accountGateway->update_address) {
|
||||
$client->address1 = trim(Input::get('address1'));
|
||||
$client->address2 = trim(Input::get('address2'));
|
||||
$client->city = trim(Input::get('city'));
|
||||
@ -471,6 +492,11 @@ class PaymentController extends BaseController
|
||||
}
|
||||
}
|
||||
} elseif ($accountGateway->gateway_id == GATEWAY_BRAINTREE) {
|
||||
$deviceData = Input::get('device_data');
|
||||
if (!$deviceData) {
|
||||
$deviceData = Session::get($invitation->id . 'device_data');
|
||||
}
|
||||
|
||||
if ($token = Input::get('payment_method_nonce')) {
|
||||
$details['token'] = $token;
|
||||
unset($details['card']);
|
||||
@ -496,6 +522,10 @@ class PaymentController extends BaseController
|
||||
return Redirect::to('payment/'.$invitationKey)->withInput(Request::except('cvv'));
|
||||
}
|
||||
}
|
||||
|
||||
if($deviceData) {
|
||||
$details['deviceData'] = $deviceData;
|
||||
}
|
||||
}
|
||||
|
||||
$response = $gateway->purchase($details)->send();
|
||||
|
@ -95,6 +95,7 @@ class PublicClientController extends BaseController
|
||||
'phone',
|
||||
]);
|
||||
|
||||
$data = array();
|
||||
$paymentTypes = $this->getPaymentTypes($client, $invitation);
|
||||
$paymentURL = '';
|
||||
if (count($paymentTypes) == 1) {
|
||||
@ -104,6 +105,12 @@ class PublicClientController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
if ($braintreeGateway = $account->getGatewayConfig(GATEWAY_BRAINTREE)){
|
||||
if($braintreeGateway->getPayPalEnabled()) {
|
||||
$data['braintreeClientToken'] = $this->paymentService->getBraintreeClientToken($account);
|
||||
}
|
||||
}
|
||||
|
||||
$showApprove = $invoice->quote_invoice_id ? false : true;
|
||||
if ($invoice->due_date) {
|
||||
$showApprove = time() < strtotime($invoice->due_date);
|
||||
@ -125,7 +132,7 @@ class PublicClientController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
$data = array(
|
||||
$data += array(
|
||||
'account' => $account,
|
||||
'showApprove' => $showApprove,
|
||||
'showBreadcrumbs' => false,
|
||||
@ -167,20 +174,28 @@ class PublicClientController extends BaseController
|
||||
|
||||
if ($paymentMethod['type']->id == PAYMENT_TYPE_ACH) {
|
||||
$html = '<div>'.htmlentities($paymentMethod['bank_name']).'</div>';
|
||||
} elseif ($paymentMethod['type']->id == PAYMENT_TYPE_ID_PAYPAL) {
|
||||
$html = '<img height="22" src="'.URL::to('/images/credit_cards/paypal.png').'" alt="'.trans("texts.card_".$code).'">';
|
||||
} else {
|
||||
$code = htmlentities(str_replace(' ', '', strtolower($paymentMethod['type']->name)));
|
||||
$html = '<img height="22" src="'.URL::to('/images/credit_cards/'.$code.'.png').'" alt="'.trans("texts.card_".$code).'">';
|
||||
}
|
||||
|
||||
if ($paymentMethod['type']->id != PAYMENT_TYPE_ACH) {
|
||||
$url = URL::to("/payment/{$invitation->invitation_key}/token/".$paymentMethod['id']);
|
||||
|
||||
if ($paymentMethod['type']->id == PAYMENT_TYPE_ID_PAYPAL) {
|
||||
$html .= ' <span>'.$paymentMethod['email'].'</span>';
|
||||
$url .= '#braintree_paypal';
|
||||
} elseif ($paymentMethod['type']->id != PAYMENT_TYPE_ACH) {
|
||||
$html .= '<div class="pull-right" style="text-align:right">'.trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($paymentMethod['expiration'], false)->format('m/y'))).'<br>';
|
||||
$html .= '•••'.$paymentMethod['last4'].'</div>';
|
||||
} else {
|
||||
$html .= '<div style="text-align:right">';
|
||||
$html .= '•••'.$paymentMethod['last4'].'</div>';
|
||||
}
|
||||
$html .= '•••'.$paymentMethod['last4'].'</div>';
|
||||
|
||||
$paymentTypes[] = [
|
||||
'url' => URL::to("/payment/{$invitation->invitation_key}/token/".$paymentMethod['id']),
|
||||
'url' => $url,
|
||||
'label' => $html,
|
||||
];
|
||||
}
|
||||
@ -219,6 +234,13 @@ class PublicClientController extends BaseController
|
||||
$paymentTypes[] = [
|
||||
'url' => $url, 'label' => $label
|
||||
];
|
||||
|
||||
if($gateway->getPayPalEnabled()) {
|
||||
$paymentTypes[] = [
|
||||
'label' => trans('texts.paypal'),
|
||||
'url' => $url = URL::to("/payment/{$invitation->invitation_key}/braintree_paypal"),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,6 +293,12 @@ class PublicClientController extends BaseController
|
||||
'paymentMethods' => $this->paymentService->getClientPaymentMethods($client),
|
||||
];
|
||||
|
||||
if ($braintreeGateway = $account->getGatewayConfig(GATEWAY_BRAINTREE)){
|
||||
if($braintreeGateway->getPayPalEnabled()) {
|
||||
$data['braintreeClientToken'] = $this->paymentService->getBraintreeClientToken($account);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->view('invited.dashboard', $data);
|
||||
}
|
||||
|
||||
@ -414,17 +442,20 @@ class PublicClientController extends BaseController
|
||||
->addColumn('transaction_reference', function ($model) { return $model->transaction_reference ? $model->transaction_reference : '<i>Manual entry</i>'; })
|
||||
->addColumn('payment_type', function ($model) { return ($model->payment_type && !$model->last4) ? $model->payment_type : ($model->account_gateway_id ? '<i>Online payment</i>' : ''); })
|
||||
->addColumn('payment_source', function ($model) {
|
||||
if (!$model->last4) return '';
|
||||
$code = str_replace(' ', '', strtolower($model->payment_type));
|
||||
$card_type = trans("texts.card_" . $code);
|
||||
if ($model->payment_type_id != PAYMENT_TYPE_ACH) {
|
||||
$expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y')));
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/' . $code . '.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4 . ' ' . $expiration;
|
||||
} else {
|
||||
if($model->last4) {
|
||||
$expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y')));
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/' . $code . '.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4 . ' ' . $expiration;
|
||||
} elseif ($model->email) {
|
||||
return $model->email;
|
||||
}
|
||||
} elseif ($model->last4) {
|
||||
$bankData = PaymentController::getBankData($model->routing_number);
|
||||
if (is_array($bankData)) {
|
||||
return $bankData['name'].' •••' . $model->last4;
|
||||
} else {
|
||||
} elseif($model->last4) {
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/ach.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4;
|
||||
}
|
||||
}
|
||||
@ -728,6 +759,12 @@ class PublicClientController extends BaseController
|
||||
'title' => trans('texts.payment_methods')
|
||||
);
|
||||
|
||||
if ($braintreeGateway = $account->getGatewayConfig(GATEWAY_BRAINTREE)){
|
||||
if($braintreeGateway->getPayPalEnabled()) {
|
||||
$data['braintreeClientToken'] = $this->paymentService->getBraintreeClientToken($account);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->view('payments.paymentmethods', $data);
|
||||
}
|
||||
|
||||
@ -771,7 +808,7 @@ class PublicClientController extends BaseController
|
||||
return redirect()->to($client->account->enable_client_portal?'/client/dashboard':'/client/paymentmethods/');
|
||||
}
|
||||
|
||||
public function addPaymentMethod($paymentType)
|
||||
public function addPaymentMethod($paymentType, $token=false)
|
||||
{
|
||||
if (!$invitation = $this->getInvitation()) {
|
||||
return $this->returnError();
|
||||
@ -785,6 +822,18 @@ class PublicClientController extends BaseController
|
||||
$paymentType = 'PAYMENT_TYPE_' . strtoupper($paymentType);
|
||||
$accountGateway = $invoice->client->account->getTokenGateway();
|
||||
$gateway = $accountGateway->gateway;
|
||||
|
||||
if ($token && $paymentType == PAYMENT_TYPE_BRAINTREE_PAYPAL) {
|
||||
$sourceId = $this->paymentService->createToken($this->paymentService->createGateway($accountGateway), array('token'=>$token), $accountGateway, $client, $invitation->contact_id);
|
||||
|
||||
if(empty($sourceId)) {
|
||||
$this->paymentMethodError('Token-No-Ref', $this->paymentService->lastError, $accountGateway);
|
||||
} else {
|
||||
Session::flash('message', trans('texts.payment_method_added'));
|
||||
}
|
||||
return redirect()->to($account->enable_client_portal?'/client/dashboard':'/client/paymentmethods/');
|
||||
}
|
||||
|
||||
$acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ Route::group(['middleware' => 'auth:client'], function() {
|
||||
Route::match(['GET', 'POST'], 'complete', 'PaymentController@offsite_payment');
|
||||
Route::get('client/paymentmethods', 'PublicClientController@paymentMethods');
|
||||
Route::post('client/paymentmethods/verify', 'PublicClientController@verifyPaymentMethod');
|
||||
Route::get('client/paymentmethods/add/{payment_type}', 'PublicClientController@addPaymentMethod');
|
||||
Route::get('client/paymentmethods/add/{payment_type}/{source_id?}', 'PublicClientController@addPaymentMethod');
|
||||
Route::post('client/paymentmethods/add/{payment_type}', 'PublicClientController@postAddPaymentMethod');
|
||||
Route::post('client/paymentmethods/default', 'PublicClientController@setDefaultPaymentMethod');
|
||||
Route::post('client/paymentmethods/{source_id}/remove', 'PublicClientController@removePaymentMethod');
|
||||
@ -638,6 +638,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('PAYMENT_TYPE_EUROCARD', 11);
|
||||
define('PAYMENT_TYPE_NOVA', 12);
|
||||
define('PAYMENT_TYPE_CREDIT_CARD_OTHER', 13);
|
||||
define('PAYMENT_TYPE_ID_PAYPAL', 14);
|
||||
define('PAYMENT_TYPE_CARTE_BLANCHE', 17);
|
||||
define('PAYMENT_TYPE_UNIONPAY', 18);
|
||||
define('PAYMENT_TYPE_JCB', 19);
|
||||
@ -650,6 +651,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('PAYMENT_TYPE_STRIPE', 'PAYMENT_TYPE_STRIPE');
|
||||
define('PAYMENT_TYPE_STRIPE_CREDIT_CARD', 'PAYMENT_TYPE_STRIPE_CREDIT_CARD');
|
||||
define('PAYMENT_TYPE_STRIPE_ACH', 'PAYMENT_TYPE_STRIPE_ACH');
|
||||
define('PAYMENT_TYPE_BRAINTREE_PAYPAL', 'PAYMENT_TYPE_BRAINTREE_PAYPAL');
|
||||
define('PAYMENT_TYPE_CREDIT_CARD', 'PAYMENT_TYPE_CREDIT_CARD');
|
||||
define('PAYMENT_TYPE_DIRECT_DEBIT', 'PAYMENT_TYPE_DIRECT_DEBIT');
|
||||
define('PAYMENT_TYPE_BITCOIN', 'PAYMENT_TYPE_BITCOIN');
|
||||
|
@ -383,6 +383,15 @@ class Account extends Eloquent
|
||||
$type = PAYMENT_TYPE_STRIPE;
|
||||
}
|
||||
|
||||
if ($type == PAYMENT_TYPE_BRAINTREE_PAYPAL) {
|
||||
$gateway = $this->getGatewayConfig(GATEWAY_BRAINTREE);
|
||||
|
||||
if (!$gateway || !$gateway->getPayPalEnabled()){
|
||||
return false;
|
||||
}
|
||||
return $gateway;
|
||||
}
|
||||
|
||||
foreach ($this->account_gateways as $gateway) {
|
||||
if (!$type || $type == PAYMENT_TYPE_ANY) {
|
||||
return $gateway;
|
||||
|
@ -77,6 +77,11 @@ class AccountGateway extends EntityModel
|
||||
return !empty($this->getConfigField('enableAch'));
|
||||
}
|
||||
|
||||
public function getPayPAlEnabled()
|
||||
{
|
||||
return !empty($this->getConfigField('enablePayPal'));
|
||||
}
|
||||
|
||||
public function getPlaidSecret()
|
||||
{
|
||||
if ( ! $this->isGateway(GATEWAY_STRIPE)) {
|
||||
|
@ -56,6 +56,7 @@ class PaymentRepository extends BaseRepository
|
||||
'payments.refunded',
|
||||
'payments.expiration',
|
||||
'payments.last4',
|
||||
'payments.email',
|
||||
'payments.routing_number',
|
||||
'invoices.is_deleted as invoice_is_deleted',
|
||||
'gateways.name as gateway_name',
|
||||
@ -119,6 +120,7 @@ class PaymentRepository extends BaseRepository
|
||||
'payments.refunded',
|
||||
'payments.expiration',
|
||||
'payments.last4',
|
||||
'payments.email',
|
||||
'payments.routing_number',
|
||||
'payments.payment_status_id',
|
||||
'payment_statuses.name as payment_status_name'
|
||||
|
@ -234,6 +234,13 @@ class PaymentService extends BaseService
|
||||
'last4' => $source->last4,
|
||||
'expiration' => $source->expirationYear . '-' . $source->expirationMonth . '-00',
|
||||
);
|
||||
} elseif ($source instanceof \Braintree\PayPalAccount) {
|
||||
$paymentMethods[] = array(
|
||||
'id' => $source->token,
|
||||
'default' => $source->isDefault(),
|
||||
'type' => $paymentTypes->find(PAYMENT_TYPE_ID_PAYPAL),
|
||||
'email' => $source->email,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -524,10 +531,16 @@ class PaymentService extends BaseService
|
||||
}
|
||||
}
|
||||
} elseif ($accountGateway->gateway_id == GATEWAY_BRAINTREE) {
|
||||
$card = $purchaseResponse->getData()->transaction->creditCardDetails;
|
||||
$payment->last4 = $card->last4;
|
||||
$payment->expiration = $card->expirationYear . '-' . $card->expirationMonth . '-00';
|
||||
$payment->payment_type_id = $this->parseCardType($card->cardType);
|
||||
$transaction = $purchaseResponse->getData()->transaction;
|
||||
if ($transaction->paymentInstrumentType == 'credit_card') {
|
||||
$card = $transaction->creditCardDetails;
|
||||
$payment->last4 = $card->last4;
|
||||
$payment->expiration = $card->expirationYear . '-' . $card->expirationMonth . '-00';
|
||||
$payment->payment_type_id = $this->parseCardType($card->cardType);
|
||||
} elseif ($transaction->paymentInstrumentType == 'paypal_account') {
|
||||
$payment->payment_type_id = PAYMENT_TYPE_ID_PAYPAL;
|
||||
$payment->email = $transaction->paypalDetails->payerEmail;
|
||||
}
|
||||
}
|
||||
|
||||
if ($payerId) {
|
||||
@ -734,17 +747,20 @@ class PaymentService extends BaseService
|
||||
[
|
||||
'source',
|
||||
function ($model) {
|
||||
if (!$model->last4) return '';
|
||||
$code = str_replace(' ', '', strtolower($model->payment_type));
|
||||
$card_type = trans("texts.card_" . $code);
|
||||
if ($model->payment_type_id != PAYMENT_TYPE_ACH) {
|
||||
$expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y')));
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/' . $code . '.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4 . ' ' . $expiration;
|
||||
} else {
|
||||
if($model->last4) {
|
||||
$expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y')));
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/' . $code . '.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4 . ' ' . $expiration;
|
||||
} elseif ($model->email) {
|
||||
return $model->email;
|
||||
}
|
||||
} elseif ($model->last4) {
|
||||
$bankData = PaymentController::getBankData($model->routing_number);
|
||||
if (is_array($bankData)) {
|
||||
return $bankData['name'].' •••' . $model->last4;
|
||||
} else {
|
||||
} elseif($model->last4) {
|
||||
return '<img height="22" src="' . URL::to('/images/credit_cards/ach.png') . '" alt="' . htmlentities($card_type) . '"> •••' . $model->last4;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class PaymentsChanges extends Migration
|
||||
$table->smallInteger('last4')->unsigned()->nullable();
|
||||
$table->date('expiration')->nullable();
|
||||
$table->text('gateway_error')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('invoices', function($table)
|
||||
@ -61,6 +62,7 @@ class PaymentsChanges extends Migration
|
||||
$table->dropColumn('last4');
|
||||
$table->dropColumn('expiration');
|
||||
$table->dropColumn('gateway_error');
|
||||
$table->dropColumn('email');
|
||||
});
|
||||
|
||||
Schema::table('invoices', function ($table) {
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@ -1276,7 +1276,13 @@ $LANG = array(
|
||||
'disabled_by_client' => 'Disabled by client',
|
||||
'manage_auto_bill' => 'Manage Auto-bill',
|
||||
'enabled' => 'Enabled',
|
||||
''
|
||||
'paypal' => 'PayPal',
|
||||
'braintree_enable_paypal' => 'Enable PayPal payments through BrainTree',
|
||||
'braintree_paypal_disabled_help' => 'The PayPal gateway is processing PayPal payments',
|
||||
'braintree_paypal_help' => 'You must also :link.',
|
||||
'braintree_paypal_help_link_text' => 'link PayPal to your BrainTree account',
|
||||
'token_billing_braintree_paypal' => 'Save payment details',
|
||||
'add_paypal_account' => 'Add PayPal Account'
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -23,6 +23,7 @@
|
||||
{!! Former::populateField('update_address', intval($accountGateway->update_address)) !!}
|
||||
{!! Former::populateField('publishable_key', $accountGateway->getPublishableStripeKey() ? str_repeat('*', strlen($accountGateway->getPublishableStripeKey())) : '') !!}
|
||||
{!! Former::populateField('enable_ach', $accountGateway->getAchEnabled() ? '1' : null) !!}
|
||||
{!! Former::populateField('enable_paypal', $accountGateway->getPayPalEnabled() ? '1' : null) !!}
|
||||
{!! Former::populateField('plaid_client_id', $accountGateway->getPlaidClientId() ? str_repeat('*', strlen($accountGateway->getPlaidClientId())) : '') !!}
|
||||
{!! Former::populateField('plaid_secret', $accountGateway->getPlaidSecret() ? str_repeat('*', strlen($accountGateway->getPlaidSecret())) : '') !!}
|
||||
{!! Former::populateField('plaid_public_key', $accountGateway->getPlaidPublicKey() ? str_repeat('*', strlen($accountGateway->getPlaidPublicKey())) : '') !!}
|
||||
@ -95,6 +96,25 @@
|
||||
->options($tokenBillingOptions)
|
||||
->help(trans('texts.token_billing_help')) !!}
|
||||
@endif
|
||||
|
||||
@if ($gateway->id == GATEWAY_BRAINTREE)
|
||||
@if ($account->getGatewayByType(PAYMENT_TYPE_PAYPAL))
|
||||
{!! Former::checkbox('enable_paypal')
|
||||
->label(trans('texts.paypal'))
|
||||
->text(trans('texts.braintree_enable_paypal'))
|
||||
->value(null)
|
||||
->disabled(true)
|
||||
->help(trans('texts.braintree_paypal_disabled_help')) !!}
|
||||
@else
|
||||
{!! Former::checkbox('enable_paypal')
|
||||
->label(trans('texts.paypal'))
|
||||
->help(trans('texts.braintree_paypal_help', [
|
||||
'link'=>'<a href="https://articles.braintreepayments.com/guides/paypal/setup-guide" target="_blank">'.
|
||||
trans('texts.braintree_paypal_help_link_text').'</a>'
|
||||
]))
|
||||
->text(trans('texts.braintree_enable_paypal')) !!}
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
@ -21,6 +21,45 @@
|
||||
margin-bottom:5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@if (!empty($braintreeClientToken))
|
||||
<script type="text/javascript" src="https://js.braintreegateway.com/js/braintree-2.23.0.min.js"></script>
|
||||
<script type="text/javascript" >
|
||||
$(function() {
|
||||
var paypalLink = $('.dropdown-menu a[href$="/braintree_paypal"]'),
|
||||
paypalUrl = paypalLink.attr('href'),
|
||||
checkout;
|
||||
paypalLink.parent().attr('id', 'paypal-container');
|
||||
braintree.setup("{{ $braintreeClientToken }}", "custom", {
|
||||
onReady: function (integration) {
|
||||
checkout = integration;
|
||||
$('.dropdown-menu a[href$="#braintree_paypal"]').each(function(){
|
||||
var el=$(this);
|
||||
el.attr('href', el.attr('href').replace('#braintree_paypal','?device_data='+encodeURIComponent(integration.deviceData)))
|
||||
})
|
||||
},
|
||||
paypal: {
|
||||
container: "paypal-container",
|
||||
singleUse: false,
|
||||
enableShippingAddress: false,
|
||||
enableBillingAddress: false,
|
||||
headless: true,
|
||||
locale: "{{$invoice->client->language?$invoice->client->language->locale:$invoice->account->language->locale}}"
|
||||
},
|
||||
dataCollector: {
|
||||
paypal: true
|
||||
},
|
||||
onPaymentMethodReceived: function (obj) {
|
||||
window.location.href = paypalUrl + '/' + encodeURIComponent(obj.nonce) + "?details=" + encodeURIComponent(JSON.stringify(obj.details))
|
||||
}
|
||||
});
|
||||
paypalLink.click(function(e){
|
||||
e.preventDefault();
|
||||
checkout.paypal.initAuthFlow();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
@ -64,7 +64,7 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@elseif ($accountGateway->getPublishableStripeKey())
|
||||
@elseif (isset($accountGateway) && $accountGateway->getPublishableStripeKey())
|
||||
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
|
||||
<script type="text/javascript">
|
||||
Stripe.setPublishableKey('{{ $accountGateway->getPublishableStripeKey() }}');
|
||||
@ -334,7 +334,8 @@
|
||||
|
||||
<p> <br/> </p>
|
||||
<div>
|
||||
@if($paymentType != PAYMENT_TYPE_STRIPE_ACH)
|
||||
<div id="paypal-container"></div>
|
||||
@if($paymentType != PAYMENT_TYPE_STRIPE_ACH && $paymentType != PAYMENT_TYPE_BRAINTREE_PAYPAL)
|
||||
<h3>{{ trans('texts.contact_information') }}</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@ -363,7 +364,7 @@
|
||||
|
||||
<p> <br/> </p>
|
||||
|
||||
@if ($showAddress)
|
||||
@if (!empty($showAddress))
|
||||
<h3>{{ trans('texts.billing_address') }} <span class="help">{{ trans('texts.payment_footer1') }}</span></h3>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@ -481,6 +482,33 @@
|
||||
->large() !!}
|
||||
@endif
|
||||
</div>
|
||||
@elseif($paymentType == PAYMENT_TYPE_BRAINTREE_PAYPAL)
|
||||
<h3>{{ trans('texts.paypal') }}</h3>
|
||||
<div>{{$paypalDetails->firstName}} {{$paypalDetails->lastName}}</div>
|
||||
<div>{{$paypalDetails->email}}</div>
|
||||
<input type="hidden" name="payment_method_nonce" value="{{$sourceId}}">
|
||||
<input type="hidden" name="first_name" value="{{$paypalDetails->firstName}}">
|
||||
<input type="hidden" name="last_name" value="{{$paypalDetails->lastName}}">
|
||||
<p> </p>
|
||||
@if (isset($amount) && $client && $account->showTokenCheckbox())
|
||||
<input id="token_billing" type="checkbox" name="token_billing" {{ $account->selectTokenCheckbox() ? 'CHECKED' : '' }} value="1" style="margin-left:0px; vertical-align:top">
|
||||
<label for="token_billing" class="checkbox" style="display: inline;">{{ trans('texts.token_billing_braintree_paypal') }}</label>
|
||||
<span class="help-block" style="font-size:15px">
|
||||
{!! trans('texts.token_billing_secure', ['link' => link_to('https://www.braintreepayments.com/', 'Braintree', ['target' => '_blank'])]) !!}
|
||||
</span>
|
||||
@endif
|
||||
<p> </p>
|
||||
<center>
|
||||
@if(isset($amount))
|
||||
{!! Button::success(strtoupper(trans('texts.pay_now') . ' - ' . $account->formatMoney($amount, $client, true) ))
|
||||
->submit()
|
||||
->large() !!}
|
||||
@else
|
||||
{!! Button::success(strtoupper(trans('texts.add_credit_card') ))
|
||||
->submit()
|
||||
->large() !!}
|
||||
@endif
|
||||
</center>
|
||||
@else
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
@ -662,7 +690,7 @@
|
||||
});
|
||||
|
||||
</script>
|
||||
@if ($accountGateway->getPlaidEnabled())
|
||||
@if (isset($accountGateway) && $accountGateway->getPlaidEnabled())
|
||||
<a href="https://plaid.com/products/auth/" target="_blank" style="display:none" id="secured_by_plaid"><img src="{{ URL::to('images/plaid-logowhite.svg') }}">{{ trans('texts.secured_by_plaid') }}</a>
|
||||
<script src="https://cdn.plaid.com/link/stable/link-initialize.js"></script>
|
||||
@endif
|
||||
|
@ -16,28 +16,65 @@
|
||||
display:inline-block;
|
||||
}
|
||||
</style>
|
||||
@if (!empty($braintreeClientToken))
|
||||
<script type="text/javascript" src="https://js.braintreegateway.com/js/braintree-2.23.0.min.js"></script>
|
||||
<script type="text/javascript" >
|
||||
$(function() {
|
||||
var paypalLink = $('#add-paypal'),
|
||||
paypalUrl = paypalLink.attr('href'),
|
||||
checkout;
|
||||
braintree.setup("{{ $braintreeClientToken }}", "custom", {
|
||||
onReady: function (integration) {
|
||||
checkout = integration;
|
||||
},
|
||||
paypal: {
|
||||
container: "paypal-container",
|
||||
singleUse: false,
|
||||
enableShippingAddress: false,
|
||||
enableBillingAddress: false,
|
||||
headless: true,
|
||||
locale: "{{$client->language?$client->language->locale:$client->account->language->locale}}"
|
||||
},
|
||||
dataCollector: {
|
||||
paypal: true
|
||||
},
|
||||
onPaymentMethodReceived: function (obj) {
|
||||
window.location.href = paypalUrl + '/' + encodeURIComponent(obj.nonce)
|
||||
}
|
||||
});
|
||||
paypalLink.click(function(e){
|
||||
e.preventDefault();
|
||||
checkout.paypal.initAuthFlow();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
@if(!empty($paymentMethods))
|
||||
@foreach ($paymentMethods as $paymentMethod)
|
||||
<div class="payment_method">
|
||||
<span class="payment_method_img_container">
|
||||
<img height="22" src="{{URL::to('/images/credit_cards/'.str_replace(' ', '', strtolower($paymentMethod['type']->name).'.png'))}}" alt="{{trans("texts.card_" . str_replace(' ', '', strtolower($paymentMethod['type']->name)))}}">
|
||||
</span>
|
||||
@if(!empty($paymentMethod['last4']))
|
||||
<span class="payment_method_number">•••••{{$paymentMethod['last4']}}</span>
|
||||
@endif
|
||||
|
||||
@if($paymentMethod['type']->id == PAYMENT_TYPE_ACH)
|
||||
{{ $paymentMethod['bank_name'] }}
|
||||
@if($paymentMethod['status'] == 'new')
|
||||
<a href="javasript::void" onclick="completeVerification('{{$paymentMethod['id']}}','{{$paymentMethod['currency']->symbol}}')">({{trans('texts.complete_verification')}})</a>
|
||||
@elseif($paymentMethod['status'] == 'verification_failed')
|
||||
({{trans('texts.verification_failed')}})
|
||||
@endif
|
||||
{{ $paymentMethod['bank_name'] }}
|
||||
@if($paymentMethod['status'] == 'new')
|
||||
<a href="javasript::void" onclick="completeVerification('{{$paymentMethod['id']}}','{{$paymentMethod['currency']->symbol}}')">({{trans('texts.complete_verification')}})</a>
|
||||
@elseif($paymentMethod['status'] == 'verification_failed')
|
||||
({{trans('texts.verification_failed')}})
|
||||
@endif
|
||||
@elseif($paymentMethod['type']->id == PAYMENT_TYPE_ID_PAYPAL)
|
||||
{{ $paymentMethod['email'] }}
|
||||
@else
|
||||
{!! trans('texts.card_expiration', array('expires'=>Utils::fromSqlDate($paymentMethod['expiration'], false)->format('m/y'))) !!}
|
||||
{!! trans('texts.card_expiration', array('expires'=>Utils::fromSqlDate($paymentMethod['expiration'], false)->format('m/y'))) !!}
|
||||
@endif
|
||||
@if($paymentMethod['default'])
|
||||
({{trans('texts.used_for_auto_bill')}})
|
||||
({{trans('texts.used_for_auto_bill')}})
|
||||
@elseif($paymentMethod['type']->id != PAYMENT_TYPE_ACH || $paymentMethod['status'] == 'verified')
|
||||
<a href="#" onclick="setDefault('{{$paymentMethod['id']}}')">({{trans('texts.use_for_auto_bill')}})</a>
|
||||
<a href="#" onclick="setDefault('{{$paymentMethod['id']}}')">({{trans('texts.use_for_auto_bill')}})</a>
|
||||
@endif
|
||||
<a href="javasript::void" class="payment_method_remove" onclick="removePaymentMethod('{{$paymentMethod['id']}}')">×</a>
|
||||
</div>
|
||||
@ -49,8 +86,15 @@
|
||||
->asLinkTo(URL::to('/client/paymentmethods/add/'.($gateway->getPaymentType() == PAYMENT_TYPE_STRIPE ? 'stripe_credit_card' : 'credit_card'))) !!}
|
||||
@if($gateway->getACHEnabled())
|
||||
|
||||
{!! Button::success(strtoupper(trans('texts.add_bank_account')))
|
||||
->asLinkTo(URL::to('/client/paymentmethods/add/stripe_ach')) !!}
|
||||
{!! Button::success(strtoupper(trans('texts.add_bank_account')))
|
||||
->asLinkTo(URL::to('/client/paymentmethods/add/stripe_ach')) !!}
|
||||
@endif
|
||||
@if($gateway->getPayPalEnabled())
|
||||
|
||||
{!! Button::success(strtoupper(trans('texts.add_paypal_account')))
|
||||
->withAttributes(['id'=>'add-paypal'])
|
||||
->asLinkTo(URL::to('/client/paymentmethods/add/braintree_paypal')) !!}
|
||||
<div id="paypal-container"></div>
|
||||
@endif
|
||||
</center>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user