1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-18 00:53:10 +01:00

Fixes for WePay

This commit is contained in:
Hillel Coren 2016-06-21 19:10:22 +03:00
parent 8a6227bf89
commit c9a19cbd76
10 changed files with 171 additions and 211 deletions

View File

@ -420,11 +420,13 @@ class Account extends Eloquent
public function paymentDriver($invitation = false, $gatewayType = false) public function paymentDriver($invitation = false, $gatewayType = false)
{ {
$accountGateway = $this->getGatewayByType($gatewayType); if ($accountGateway = $this->getGatewayByType($gatewayType)) {
return $accountGateway->paymentDriver($invitation, $gatewayType); return $accountGateway->paymentDriver($invitation, $gatewayType);
} }
return false;
}
public function gatewayIds() public function gatewayIds()
{ {
return $this->account_gateways()->pluck('gateway_id')->toArray(); return $this->account_gateways()->pluck('gateway_id')->toArray();

View File

@ -136,6 +136,7 @@ class AccountGateway extends EntityModel
public function getWebhookUrl() public function getWebhookUrl()
{ {
$account = $this->account ? $this->account : Account::find($this->account_id); $account = $this->account ? $this->account : Account::find($this->account_id);
return \URL::to(env('WEBHOOK_PREFIX','').'paymenthook/'.$account->account_key.'/'.$this->gateway_id.env('WEBHOOK_SUFFIX','')); return \URL::to(env('WEBHOOK_PREFIX','').'paymenthook/'.$account->account_key.'/'.$this->gateway_id.env('WEBHOOK_SUFFIX',''));
} }
} }

View File

@ -26,7 +26,7 @@ class BasePaymentDriver
protected $tokenResponse; protected $tokenResponse;
protected $purchaseResponse; protected $purchaseResponse;
protected $sourceReferenceParam; protected $sourceReferenceParam = 'token';
protected $customerReferenceParam; protected $customerReferenceParam;
protected $transactionReferenceParam; protected $transactionReferenceParam;
@ -119,6 +119,7 @@ class BasePaymentDriver
} }
$data = [ $data = [
'details' => ! empty($input['details']) ? json_decode($input['details']) : false,
'accountGateway' => $this->accountGateway, 'accountGateway' => $this->accountGateway,
'acceptedCreditCardTypes' => $this->accountGateway->getCreditcardTypes(), 'acceptedCreditCardTypes' => $this->accountGateway->getCreditcardTypes(),
'gateway' => $gateway, 'gateway' => $gateway,

View File

@ -1,5 +1,7 @@
<?php namespace App\Ninja\PaymentDrivers; <?php namespace App\Ninja\PaymentDrivers;
use Session;
use Utils;
use Exception; use Exception;
class WePayPaymentDriver extends BasePaymentDriver class WePayPaymentDriver extends BasePaymentDriver
@ -54,7 +56,7 @@ class WePayPaymentDriver extends BasePaymentDriver
{ {
$data = parent::paymentDetails($paymentMethod); $data = parent::paymentDetails($paymentMethod);
if ($transactionId = Session::get($invitation->id . 'payment_ref')) { if ($transactionId = Session::get($this->invitation->id . 'payment_ref')) {
$data['transaction_id'] = $transactionId; $data['transaction_id'] = $transactionId;
} }
@ -69,25 +71,109 @@ class WePayPaymentDriver extends BasePaymentDriver
return $data; return $data;
} }
public function createToken()
{
$wepay = Utils::setupWePay($this->accountGateway);
$token = intval($this->input['sourceToken']);
if ($this->isGatewayType(GATEWAY_TYPE_BANK_TRANSFER)) {
// Persist bank details
$this->tokenResponse = $wepay->request('/payment_bank/persist', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'payment_bank_id' => $token,
));
} else {
// Authorize credit card
$tokenResponse = $wepay->request('credit_card/authorize', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => $token,
));
// Update the callback uri and get the card details
$tokenResponse = $wepay->request('credit_card/modify', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => $token,
'auto_update' => WEPAY_AUTO_UPDATE,
'callback_uri' => $this->accountGateway->getWebhookUrl(),
));
$this->tokenResponse = $wepay->request('credit_card', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => $token,
));
}
return parent::createToken();
}
/*
public function creatingCustomer($customer)
{
if ($gatewayResponse instanceof \Omnipay\WePay\Message\CustomCheckoutResponse) {
$wepay = \Utils::setupWePay($accountGateway);
$paymentMethodType = $gatewayResponse->getData()['payment_method']['type'];
$gatewayResponse = $wepay->request($paymentMethodType, array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
$paymentMethodType.'_id' => $gatewayResponse->getData()['payment_method'][$paymentMethodType]['id'],
));
}
}
*/
protected function creatingPaymentMethod($paymentMethod)
{
$source = $this->tokenResponse;
if ($this->isGatewayType(GATEWAY_TYPE_BANK_TRANSFER)) {
$paymentMethod->payment_type_id = PAYMENT_TYPE_ACH;
$paymentMethod->last4 = $source->account_last_four;
$paymentMethod->bank_name = $source->bank_name;
$paymentMethod->source_reference = $source->payment_bank_id;
switch($source->state) {
case 'new':
case 'pending':
$paymentMethod->status = 'new';
break;
case 'authorized':
$paymentMethod->status = 'verified';
break;
}
} else {
$paymentMethod->last4 = $source->last_four;
$paymentMethod->payment_type_id = $this->parseCardType($source->credit_card_name);
$paymentMethod->expiration = $source->expiration_year . '-' . $source->expiration_month . '-01';
$paymentMethod->source_reference = $source->credit_card_id;
}
return $paymentMethod;
}
public function removePaymentMethod($paymentMethod) public function removePaymentMethod($paymentMethod)
{ {
$wepay = Utils::setupWePay($this->accountGateway); $wepay = Utils::setupWePay($this->accountGateway);
$wepay->request('/credit_card/delete', [ $response = $wepay->request('/credit_card/delete', [
'client_id' => WEPAY_CLIENT_ID, 'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET, 'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => intval($paymentMethod->source_reference), 'credit_card_id' => intval($paymentMethod->source_reference),
]); ]);
if ($response->isSuccessful()) { if ($response->state == 'deleted') {
return parent::removePaymentMethod($paymentMethod); return parent::removePaymentMethod($paymentMethod);
} else { } else {
throw new Exception($response->getMessage()); throw new Exception();
} }
} }
protected function refundDetails($payment, $amount) protected function refundDetails($payment, $amount)
{ {
$data = parent::refundDetails($parent); $data = parent::refundDetails($payment, $amount);
$data['refund_reason'] = 'Refund issued by merchant.'; $data['refund_reason'] = 'Refund issued by merchant.';

View File

@ -43,143 +43,6 @@ class PaymentService extends BaseService
return $this->paymentRepo; return $this->paymentRepo;
} }
public function createToken($paymentType, $gateway, $details, $accountGateway, $client, $contactId, &$customerReference = null, &$paymentMethod = null)
{
if ($accountGateway->gateway_id == GATEWAY_BRAINTREE) {
} elseif ($accountGateway->gateway_id == GATEWAY_WEPAY) {
$wepay = Utils::setupWePay($accountGateway);
try {
if ($paymentType == PAYMENT_TYPE_WEPAY_ACH) {
// Persist bank details
$tokenResponse = $wepay->request('/payment_bank/persist', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'payment_bank_id' => intval($details['token']),
));
} else {
// Authorize credit card
$wepay->request('credit_card/authorize', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => intval($details['token']),
));
// Update the callback uri and get the card details
$wepay->request('credit_card/modify', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => intval($details['token']),
'auto_update' => WEPAY_AUTO_UPDATE,
'callback_uri' => $accountGateway->getWebhookUrl(),
));
$tokenResponse = $wepay->request('credit_card', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'credit_card_id' => intval($details['token']),
));
}
$customerReference = CUSTOMER_REFERENCE_LOCAL;
$sourceReference = $details['token'];
} catch (\WePayException $ex) {
$this->lastError = $ex->getMessage();
return;
}
} else {
return null;
}
if ($customerReference) {
$accountGatewayToken = AccountGatewayToken::where('client_id', '=', $client->id)
->where('account_gateway_id', '=', $accountGateway->id)->first();
if (!$accountGatewayToken) {
$accountGatewayToken = new AccountGatewayToken();
$accountGatewayToken->account_id = $client->account->id;
$accountGatewayToken->contact_id = $contactId;
$accountGatewayToken->account_gateway_id = $accountGateway->id;
$accountGatewayToken->client_id = $client->id;
}
$accountGatewayToken->token = $customerReference;
$accountGatewayToken->save();
$paymentMethod = $this->convertPaymentMethodFromGatewayResponse($tokenResponse, $accountGateway, $accountGatewayToken, $contactId);
$paymentMethod->ip = \Request::ip();
$paymentMethod->save();
} else {
$this->lastError = $tokenResponse->getMessage();
}
return $sourceReference;
}
public function convertPaymentMethodFromWePay($source, $accountGatewayToken = null, $paymentMethod = null) {
// Creating a new one or updating an existing one
if (!$paymentMethod) {
$paymentMethod = $accountGatewayToken ? PaymentMethod::createNew($accountGatewayToken) : new PaymentMethod();
}
if ($source->payment_bank_id) {
$paymentMethod->payment_type_id = PAYMENT_TYPE_ACH;
$paymentMethod->last4 = $source->account_last_four;
$paymentMethod->bank_name = $source->bank_name;
$paymentMethod->source_reference = $source->payment_bank_id;
switch($source->state) {
case 'new':
case 'pending':
$paymentMethod->status = 'new';
break;
case 'authorized':
$paymentMethod->status = 'verified';
break;
}
} else {
$paymentMethod->last4 = $source->last_four;
$paymentMethod->payment_type_id = $this->parseCardType($source->credit_card_name);
$paymentMethod->expiration = $source->expiration_year . '-' . $source->expiration_month . '-01';
$paymentMethod->setRelation('payment_type', Cache::get('paymentTypes')->find($paymentMethod->payment_type_id));
$paymentMethod->source_reference = $source->credit_card_id;
}
return $paymentMethod;
}
public function convertPaymentMethodFromGatewayResponse($gatewayResponse, $accountGateway, $accountGatewayToken = null, $contactId = null, $existingPaymentMethod = null) {
if ($accountGateway->gateway_id == GATEWAY_WEPAY) {
if ($gatewayResponse instanceof \Omnipay\WePay\Message\CustomCheckoutResponse) {
$wepay = \Utils::setupWePay($accountGateway);
$paymentMethodType = $gatewayResponse->getData()['payment_method']['type'];
$gatewayResponse = $wepay->request($paymentMethodType, array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
$paymentMethodType.'_id' => $gatewayResponse->getData()['payment_method'][$paymentMethodType]['id'],
));
}
$paymentMethod = $this->convertPaymentMethodFromWePay($gatewayResponse, $accountGatewayToken, $existingPaymentMethod);
}
if (!empty($paymentMethod) && $accountGatewayToken && $contactId) {
$paymentMethod->account_gateway_token_id = $accountGatewayToken->id;
$paymentMethod->account_id = $accountGatewayToken->account_id;
$paymentMethod->contact_id = $contactId;
$paymentMethod->save();
if (!$paymentMethod->account_gateway_token->default_payment_method_id) {
$paymentMethod->account_gateway_token->default_payment_method_id = $paymentMethod->id;
$paymentMethod->account_gateway_token->save();
}
}
return $paymentMethod;
}
public function autoBillInvoice($invoice) public function autoBillInvoice($invoice)
{ {
$client = $invoice->client; $client = $invoice->client;

View File

@ -74,7 +74,7 @@ class PaymentLibrariesSeeder extends Seeder
['name' => 'Secure Trading', 'provider' => 'SecureTrading'], ['name' => 'Secure Trading', 'provider' => 'SecureTrading'],
['name' => 'SecPay', 'provider' => 'SecPay'], ['name' => 'SecPay', 'provider' => 'SecPay'],
['name' => 'WeChat Express', 'provider' => 'WeChat_Express'], ['name' => 'WeChat Express', 'provider' => 'WeChat_Express'],
['name' => 'WePay', 'provider' => 'WePay'], ['name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false],
['name' => 'Braintree', 'provider' => 'Braintree'], ['name' => 'Braintree', 'provider' => 'Braintree'],
]; ];
@ -82,7 +82,7 @@ class PaymentLibrariesSeeder extends Seeder
$record = Gateway::where('name', '=', $gateway['name'])->first(); $record = Gateway::where('name', '=', $gateway['name'])->first();
if ($record) { if ($record) {
$record->provider = $gateway['provider']; $record->provider = $gateway['provider'];
$record->is_offsite = isset($gateway['is_offsite']); $record->is_offsite = isset($gateway['is_offsite']) ? boolval($gateway['is_offsite']) : false;
$record->save(); $record->save();
} else { } else {
Gateway::create($gateway); Gateway::create($gateway);

View File

@ -30,7 +30,6 @@
var paypalLink = $('.dropdown-menu a[href$="paypal"]'), var paypalLink = $('.dropdown-menu a[href$="paypal"]'),
paypalUrl = paypalLink.attr('href'), paypalUrl = paypalLink.attr('href'),
checkout; checkout;
console.log(paypalUrl);
paypalLink.parent().attr('id', 'paypal-container'); paypalLink.parent().attr('id', 'paypal-container');
braintree.setup("{{ $transactionToken }}", "custom", { braintree.setup("{{ $transactionToken }}", "custom", {
onReady: function (integration) { onReady: function (integration) {
@ -65,7 +64,7 @@
<script type="text/javascript" src="https://static.wepay.com/js/tokenization.v2.js"></script> <script type="text/javascript" src="https://static.wepay.com/js/tokenization.v2.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
var achLink = $('.dropdown-menu a[href$="/wepay_ach"]'), var achLink = $('.dropdown-menu a[href$="/bank_transfer"]'),
achUrl = achLink.attr('href'); achUrl = achLink.attr('href');
WePay.set_endpoint('{{ WEPAY_ENVIRONMENT }}'); WePay.set_endpoint('{{ WEPAY_ENVIRONMENT }}');
achLink.click(function(e) { achLink.click(function(e) {

View File

@ -1,62 +0,0 @@
<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.v2.js"></script>
<script type="text/javascript">
$(function() {
var countries = {!! $countries->pluck('iso_3166_2','id') !!};
WePay.set_endpoint('{{ WEPAY_ENVIRONMENT }}');
var $form = $('.payment-form');
$('.payment-form').submit(function(event) {
var data = {
client_id: {{ WEPAY_CLIENT_ID }},
user_name: $('#first_name').val() + ' ' + $('#last_name').val(),
email: $('#email').val(),
cc_number: $('#card_number').val(),
cvv: $('#cvv').val(),
expiration_month: $('#expiration_month').val(),
expiration_year: $('#expiration_year').val(),
address: {
address1: $('#address1').val(),
address2: $('#address2').val(),
city: $('#city').val(),
country: countries[$("#country_id").val()]
}
};
if(data.address.country == 'US') {
data.address.zip = $('#postal_code').val();
} else {
data.address.postcode = $('#postal_code').val();
}
// Not including state/province, since WePay wants 2-letter codes and users enter the full name
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
$('#js-error-message').hide();
var response = WePay.credit_card.create(data, function(response) {
if (response.error) {
// Show the errors on the form
var error = response.error_description;
$form.find('button').prop('disabled', false);
$('#js-error-message').text(error).fadeIn();
} else {
// response contains id and card, which contains additional card details
var token = response.credit_card_id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="sourceToken"/>').val(token));
// and submit
$form.get(0).submit();
}
});
if (response.error) {
// Show the errors on the form
var error = response.error_description;
$form.find('button').prop('disabled', false);
$('#js-error-message').text(error).fadeIn();
}
// Prevent the form from submitting with the default action
return false;
});
});
</script>

View File

@ -2,6 +2,8 @@
@section('payment_details') @section('payment_details')
{!! Former::vertical_open($url) !!}
<h3>{{ trans('texts.bank_account') }}</h3> <h3>{{ trans('texts.bank_account') }}</h3>
@if (!empty($details)) @if (!empty($details))

View File

@ -0,0 +1,68 @@
@extends('payments.credit_card')
@section('head')
@parent
<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.v2.js"></script>
<script type="text/javascript">
$(function() {
var countries = {!! Cache::get('countries')->pluck('iso_3166_2','id') !!};
WePay.set_endpoint('{{ WEPAY_ENVIRONMENT }}');
var $form = $('.payment-form');
$('.payment-form').submit(function(event) {
var data = {
client_id: {{ WEPAY_CLIENT_ID }},
user_name: $('#first_name').val() + ' ' + $('#last_name').val(),
email: $('#email').val(),
cc_number: $('#card_number').val(),
cvv: $('#cvv').val(),
expiration_month: $('#expiration_month').val(),
expiration_year: $('#expiration_year').val(),
address: {
address1: $('#address1').val(),
address2: $('#address2').val(),
city: $('#city').val(),
country: countries[$("#country_id").val()]
}
};
if(data.address.country == 'US') {
data.address.zip = $('#postal_code').val();
} else {
data.address.postcode = $('#postal_code').val();
}
// Not including state/province, since WePay wants 2-letter codes and users enter the full name
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
$('#js-error-message').hide();
var response = WePay.credit_card.create(data, function(response) {
if (response.error) {
// Show the errors on the form
var error = response.error_description;
$form.find('button').prop('disabled', false);
$('#js-error-message').text(error).fadeIn();
} else {
// response contains id and card, which contains additional card details
var token = response.credit_card_id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="sourceToken"/>').val(token));
// and submit
$form.get(0).submit();
}
});
if (response.error) {
// Show the errors on the form
var error = response.error_description;
$form.find('button').prop('disabled', false);
$('#js-error-message').text(error).fadeIn();
}
// Prevent the form from submitting with the default action
return false;
});
});
</script>
@stop