mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 22:27:31 -05:00 
			
		
		
		
	
						commit
						5ea07be358
					
				@ -74,9 +74,9 @@ class PaymentWebhookRequest extends Request
 | 
			
		||||
    {
 | 
			
		||||
        // For testing purposes we'll slow down the webhook processing by 2 seconds
 | 
			
		||||
        // to make sure webhook request doesn't came before our processing.
 | 
			
		||||
        if (app()->environment() !== 'production') {
 | 
			
		||||
        //if (app()->environment() !== 'production') {
 | 
			
		||||
            sleep(2);
 | 
			
		||||
        }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        // Some gateways, like Checkout, we can dynamically pass payment hash,
 | 
			
		||||
        // which we will resolve here and get payment information from it.
 | 
			
		||||
 | 
			
		||||
@ -133,6 +133,7 @@ class PaymentEmailEngine extends BaseEmailEngine
 | 
			
		||||
        $data['$email'] = ['value' => isset($this->contact) ? $this->contact->email : 'no contact email on record', 'label' => ctrans('texts.email')];
 | 
			
		||||
        $data['$client_name'] = ['value' => $this->client->present()->name() ?: ' ', 'label' => ctrans('texts.client_name')];
 | 
			
		||||
        $data['$client.name'] = &$data['$client_name'];
 | 
			
		||||
        $data['$client'] = &$data['$client_name'];
 | 
			
		||||
        $data['$client.address1'] = &$data['$address1'];
 | 
			
		||||
        $data['$client.address2'] = &$data['$address2'];
 | 
			
		||||
        $data['$client_address'] = ['value' => $this->client->present()->address() ?: ' ', 'label' => ctrans('texts.address')];
 | 
			
		||||
 | 
			
		||||
@ -60,11 +60,12 @@ class SupportMessageSent extends Mailable
 | 
			
		||||
 | 
			
		||||
        $company = auth()->user()->company();
 | 
			
		||||
        $user = auth()->user();
 | 
			
		||||
        $db = str_replace("db-ninja-", "", $company->db);
 | 
			
		||||
 | 
			
		||||
        if(Ninja::isHosted())
 | 
			
		||||
            $subject = "{$priority}Hosted-{$company->db} :: Customer Support - {$plan} ".date('M jS, g:ia');
 | 
			
		||||
            $subject = "{$priority}Hosted-{$company->db} :: {$plan} :: ".date('M jS, g:ia');
 | 
			
		||||
        else
 | 
			
		||||
            $subject = "{$priority}Self Hosted :: Customer Support - [{$plan}] ".date('M jS, g:ia');
 | 
			
		||||
            $subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia');
 | 
			
		||||
 | 
			
		||||
        return $this->from(config('mail.from.address'), $user->present()->name()) 
 | 
			
		||||
                ->replyTo($user->email, $user->present()->name())
 | 
			
		||||
 | 
			
		||||
@ -69,16 +69,20 @@ class CompanyGateway extends BaseModel
 | 
			
		||||
    // const TYPE_CUSTOM = 306;
 | 
			
		||||
    // const TYPE_BRAINTREE = 307;
 | 
			
		||||
    // const TYPE_WEPAY = 309;
 | 
			
		||||
    // const TYPE_PAYFAST = 310;
 | 
			
		||||
    // const TYPE_PAYTRACE = 311;
 | 
			
		||||
 | 
			
		||||
    public $gateway_consts = [
 | 
			
		||||
        '38f2c48af60c7dd69e04248cbb24c36e' => 300,
 | 
			
		||||
        'd14dd26a37cecc30fdd65700bfb55b23' => 301,
 | 
			
		||||
        'd14dd26a47cecc30fdd65700bfb67b34' => 301,
 | 
			
		||||
        '3758e7f7c6f4cecf0f4f348b9a00f456' => 304,
 | 
			
		||||
        '3b6621f970ab18887c4f6dca78d3f8bb' => 305,
 | 
			
		||||
        '54faab2ab6e3223dbe848b1686490baa' => 306,
 | 
			
		||||
        'd14dd26a47cecc30fdd65700bfb67b34' => 301,
 | 
			
		||||
        '8fdeed552015b3c7b44ed6c8ebd9e992' => 309,
 | 
			
		||||
        'f7ec488676d310683fb51802d076d713' => 307,
 | 
			
		||||
        '8fdeed552015b3c7b44ed6c8ebd9e992' => 309,
 | 
			
		||||
        'd6814fc83f45d2935e7777071e629ef9' => 310,
 | 
			
		||||
        'bbd736b3254b0aabed6ad7fda1298c88' => 311,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    protected $touches = [];
 | 
			
		||||
 | 
			
		||||
@ -81,6 +81,9 @@ class Gateway extends StaticModel
 | 
			
		||||
            case 1:
 | 
			
		||||
                return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net
 | 
			
		||||
                break;
 | 
			
		||||
            case 1:
 | 
			
		||||
                return [GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false]];//Payfast
 | 
			
		||||
                break;
 | 
			
		||||
            case 15:
 | 
			
		||||
                return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal
 | 
			
		||||
                break;
 | 
			
		||||
@ -95,6 +98,8 @@ class Gateway extends StaticModel
 | 
			
		||||
            case 39:
 | 
			
		||||
                return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout
 | 
			
		||||
                break;
 | 
			
		||||
            case 46:
 | 
			
		||||
                return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Paytrace
 | 
			
		||||
            case 49:
 | 
			
		||||
                return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true],
 | 
			
		||||
                    GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true]]; //WePay
 | 
			
		||||
 | 
			
		||||
@ -68,7 +68,7 @@ class SystemLog extends Model
 | 
			
		||||
    const TYPE_BRAINTREE = 307;
 | 
			
		||||
    const TYPE_WEPAY = 309;
 | 
			
		||||
    const TYPE_PAYFAST = 310;
 | 
			
		||||
    
 | 
			
		||||
    const TYPE_PAYTRACE = 311;
 | 
			
		||||
 | 
			
		||||
    const TYPE_QUOTA_EXCEEDED = 400;
 | 
			
		||||
    const TYPE_UPSTREAM_FAILURE = 401;
 | 
			
		||||
 | 
			
		||||
@ -431,6 +431,61 @@ class BaseDriver extends AbstractPaymentDriver
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Generic Global unsuccessful transaction method when the client is present*/
 | 
			
		||||
    public function processUnsuccessfulTransaction($response, $client_present = true)
 | 
			
		||||
    {
 | 
			
		||||
        $error = $response['error'];
 | 
			
		||||
        $error_code = $response['error_code'];
 | 
			
		||||
 | 
			
		||||
        $this->unWindGatewayFees($this->payment_hash);
 | 
			
		||||
 | 
			
		||||
        PaymentFailureMailer::dispatch($this->client, $error, $this->client->company, $this->payment_hash->data->amount_with_fee);
 | 
			
		||||
 | 
			
		||||
        $nmo = new NinjaMailerObject;
 | 
			
		||||
        $nmo->mailable = new NinjaMailer( (new ClientPaymentFailureObject($this->client, $error, $this->client->company, $this->payment_hash))->build() );
 | 
			
		||||
        $nmo->company = $this->client->company;
 | 
			
		||||
        $nmo->settings = $this->client->company->settings;
 | 
			
		||||
 | 
			
		||||
        $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
 | 
			
		||||
 | 
			
		||||
        $invoices->each(function ($invoice){
 | 
			
		||||
 | 
			
		||||
            $invoice->service()->deletePdf();
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $invoices->first()->invitations->each(function ($invitation) use ($nmo){
 | 
			
		||||
 | 
			
		||||
            if ($invitation->contact->send_email && $invitation->contact->email) {
 | 
			
		||||
 | 
			
		||||
                $nmo->to_user = $invitation->contact;
 | 
			
		||||
                NinjaMailerJob::dispatch($nmo);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $message = [
 | 
			
		||||
            'server_response' => $response,
 | 
			
		||||
            'data' => $this->payment_hash->data,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        SystemLogger::dispatch(
 | 
			
		||||
            $message,
 | 
			
		||||
            SystemLog::CATEGORY_GATEWAY_RESPONSE,
 | 
			
		||||
            SystemLog::EVENT_GATEWAY_FAILURE,
 | 
			
		||||
            $this::SYSTEM_LOG_TYPE,
 | 
			
		||||
            $this->client,
 | 
			
		||||
            $this->client->company,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if($client_present)
 | 
			
		||||
            throw new PaymentFailed($error, 500);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function checkRequirements()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->company_gateway->require_billing_address) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										256
									
								
								app/PaymentDrivers/PayTrace/CreditCard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								app/PaymentDrivers/PayTrace/CreditCard.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,256 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Invoice Ninja (https://invoiceninja.com).
 | 
			
		||||
 *
 | 
			
		||||
 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
			
		||||
 *
 | 
			
		||||
 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
			
		||||
 *
 | 
			
		||||
 * @license https://www.elastic.co/licensing/elastic-license
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace App\PaymentDrivers\PayTrace;
 | 
			
		||||
 | 
			
		||||
use App\Exceptions\PaymentFailed;
 | 
			
		||||
use App\Jobs\Mail\PaymentFailureMailer;
 | 
			
		||||
use App\Jobs\Util\SystemLogger;
 | 
			
		||||
use App\Models\ClientGatewayToken;
 | 
			
		||||
use App\Models\GatewayType;
 | 
			
		||||
use App\Models\Invoice;
 | 
			
		||||
use App\Models\Payment;
 | 
			
		||||
use App\Models\PaymentHash;
 | 
			
		||||
use App\Models\PaymentType;
 | 
			
		||||
use App\Models\SystemLog;
 | 
			
		||||
use App\PaymentDrivers\PayFastPaymentDriver;
 | 
			
		||||
use App\PaymentDrivers\PaytracePaymentDriver;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Support\Facades\Cache;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class CreditCard
 | 
			
		||||
{
 | 
			
		||||
    use MakesHash;
 | 
			
		||||
 | 
			
		||||
    public $paytrace_driver;
 | 
			
		||||
 | 
			
		||||
    public function __construct(PaytracePaymentDriver $paytrace_driver)
 | 
			
		||||
    {
 | 
			
		||||
        $this->paytrace_driver = $paytrace_driver;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function authorizeView($data)
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
        $data['client_key'] = $this->paytrace_driver->getAuthToken();
 | 
			
		||||
        $data['gateway'] = $this->paytrace_driver;
 | 
			
		||||
 | 
			
		||||
        return render('gateways.paytrace.authorize', $data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // +"success": true
 | 
			
		||||
    // +"response_code": 160
 | 
			
		||||
    // +"status_message": "The customer profile for PLS5U60OoLUfQXzcmtJYNefPA0gTthzT/11 was successfully created."
 | 
			
		||||
    // +"customer_id": "PLS5U60OoLUfQXzcmtJYNefPA0gTthzT"
 | 
			
		||||
 | 
			
		||||
    //if(!$response->success)
 | 
			
		||||
    //handle failure
 | 
			
		||||
        
 | 
			
		||||
 	public function authorizeResponse($request)
 | 
			
		||||
 	{
 | 
			
		||||
        $data = $request->all();
 | 
			
		||||
        
 | 
			
		||||
        $response = $this->createCustomer($data);   
 | 
			
		||||
 | 
			
		||||
        return redirect()->route('client.payment_methods.index');
 | 
			
		||||
 | 
			
		||||
 	}  
 | 
			
		||||
    
 | 
			
		||||
    //  "_token" => "Vl1xHflBYQt9YFSaNCPTJKlY5x3rwcFE9kvkw71I"
 | 
			
		||||
    //   "company_gateway_id" => "1"
 | 
			
		||||
    //   "HPF_Token" => "e484a92c-90ed-4468-ac4d-da66824c75de"
 | 
			
		||||
    //   "enc_key" => "zqz6HMHCXALWdX5hyBqrIbSwU7TBZ0FTjjLB3Cp0FQY="
 | 
			
		||||
    //   "amount" => "Amount"
 | 
			
		||||
    //   "q" => "/client/payment_methods"
 | 
			
		||||
    //   "method" => "1"
 | 
			
		||||
    // ]
 | 
			
		||||
 | 
			
		||||
    // "customer_id":"customer789",
 | 
			
		||||
    // "hpf_token":"e369847e-3027-4174-9161-fa0d4e98d318",
 | 
			
		||||
    // "enc_key":"lI785yOBMet4Rt9o4NLXEyV84WBU3tdStExcsfoaOoo=",
 | 
			
		||||
    // "integrator_id":"xxxxxxxxxx",
 | 
			
		||||
    // "billing_address":{
 | 
			
		||||
    //     "name":"Mark Smith",
 | 
			
		||||
    //     "street_address":"8320 E. West St.",
 | 
			
		||||
    //     "city":"Spokane",
 | 
			
		||||
    //     "state":"WA",
 | 
			
		||||
    //     "zip":"85284"
 | 
			
		||||
    // }
 | 
			
		||||
    
 | 
			
		||||
    private function createCustomer($data)
 | 
			
		||||
    {
 | 
			
		||||
        $post_data = [
 | 
			
		||||
            'customer_id' => Str::random(32),
 | 
			
		||||
            'hpf_token' => $data['HPF_Token'],
 | 
			
		||||
            'enc_key' => $data['enc_key'],
 | 
			
		||||
            'integrator_id' =>  $this->company_gateway->getConfigField('integratorId'),
 | 
			
		||||
            'billing_address' => $this->buildBillingAddress(),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $response = $this->paytrace_driver->gatewayRequest('/v1/customer/pt_protect_create', $post_data);
 | 
			
		||||
 | 
			
		||||
        $cgt = [];
 | 
			
		||||
        $cgt['token'] = $response->customer_id;
 | 
			
		||||
        $cgt['payment_method_id'] = GatewayType::CREDIT_CARD;
 | 
			
		||||
 | 
			
		||||
        $profile = $this->getCustomerProfile($response->customer_id);
 | 
			
		||||
 | 
			
		||||
        $payment_meta = new \stdClass;
 | 
			
		||||
        $payment_meta->exp_month = $profile->credit_card->expiration_month;
 | 
			
		||||
        $payment_meta->exp_year = $profile->credit_card->expiration_year;
 | 
			
		||||
        $payment_meta->brand = 'CC';
 | 
			
		||||
        $payment_meta->last4 = $profile->credit_card->masked_number;
 | 
			
		||||
        $payment_meta->type = GatewayType::CREDIT_CARD;
 | 
			
		||||
 | 
			
		||||
        $cgt['payment_meta'] = $payment_meta;
 | 
			
		||||
 | 
			
		||||
        $token = $this->paytrace_driver->storeGatewayToken($cgt, []);
 | 
			
		||||
 | 
			
		||||
        return $response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getCustomerProfile($customer_id)
 | 
			
		||||
    {
 | 
			
		||||
        $profile = $this->paytrace_driver->gatewayRequest('/v1/customer/export', [
 | 
			
		||||
            'integrator_id' =>  $this->company_gateway->getConfigField('integratorId'),
 | 
			
		||||
            'customer_id' => $customer_id,
 | 
			
		||||
            // 'include_bin' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        return $profile->customers[0];
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function buildBillingAddress()
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
                'name' => $this->paytrace_driver->client->present()->name(),
 | 
			
		||||
                'street_address' => $this->paytrace_driver->client->address1,
 | 
			
		||||
                'city' => $this->paytrace_driver->client->city,
 | 
			
		||||
                'state' => $this->paytrace_driver->client->state,
 | 
			
		||||
                'zip' => $this->paytrace_driver->client->postal_code
 | 
			
		||||
            ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function paymentView($data)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $data['client_key'] = $this->paytrace_driver->getAuthToken();
 | 
			
		||||
        $data['gateway'] = $this->paytrace_driver;
 | 
			
		||||
 | 
			
		||||
        return render('gateways.paytrace.pay', $data);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function paymentResponse(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $response_array = $request->all();
 | 
			
		||||
 | 
			
		||||
        if($request->token)
 | 
			
		||||
            $this->processTokenPayment($request->token, $request);
 | 
			
		||||
 | 
			
		||||
        if ($request->has('store_card') && $request->input('store_card') === true) {
 | 
			
		||||
 | 
			
		||||
            $response = $this->createCustomer($request->all());
 | 
			
		||||
            
 | 
			
		||||
            $this->processTokenPayment($response->customer_id, $request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //process a regular charge here:
 | 
			
		||||
        $data = [
 | 
			
		||||
            'hpf_token' => $response_array['HPF_Token'],
 | 
			
		||||
            'enc_key' => $response_array['enc_key'],
 | 
			
		||||
            'integrator_id' =>  $this->company_gateway->getConfigField('integratorId'),
 | 
			
		||||
            'billing_address' => $this->buildBillingAddress(),
 | 
			
		||||
            'amount' => $request->input('amount_with_fee'),
 | 
			
		||||
            'invoice_id' => $this->harvestInvoiceId(),
 | 
			
		||||
        ];        
 | 
			
		||||
 | 
			
		||||
        $response = $this->paytrace_driver->gatewayRequest('/v1/transactions/sale/pt_protect', $data);
 | 
			
		||||
 | 
			
		||||
        if($response->success)
 | 
			
		||||
            return $this->processSuccessfulPayment($response);
 | 
			
		||||
 | 
			
		||||
        return $this->processUnsuccessfulPayment($response);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function processTokenPayment($token, $request)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'customer_id' => $request->token,
 | 
			
		||||
            'integrator_id' =>  $this->company_gateway->getConfigField('integratorId'),
 | 
			
		||||
            'amount' => $request->input('amount_with_fee'),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $response = $this->paytrace_driver->gatewayRequest('/v1/transactions/sale/by_customer', $data);
 | 
			
		||||
 | 
			
		||||
        if($response->success){
 | 
			
		||||
            $this->paytrace_driver->logSuccessfulGatewayResponse(['response' => $response, 'data' => $this->paytrace_driver->payment_hash], SystemLog::TYPE_PAYTRACE);
 | 
			
		||||
 | 
			
		||||
            return $this->processSuccessfulPayment($response);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->processUnsuccessfulPayment($response);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private function harvestInvoiceId()
 | 
			
		||||
    {
 | 
			
		||||
        $_invoice = collect($this->paytrace_driver->payment_hash->data->invoices)->first();
 | 
			
		||||
        $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
 | 
			
		||||
 | 
			
		||||
        if($invoice)
 | 
			
		||||
            return ctrans('texts.invoice_number') . "# " . $invoice->number;
 | 
			
		||||
 | 
			
		||||
        return ctrans('texts.invoice_number') . "####";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function processSuccessfulPayment($response)
 | 
			
		||||
    {
 | 
			
		||||
        $amount = array_sum(array_column($this->paytrace_driver->payment_hash->invoices(), 'amount')) + $this->paytrace_driver->payment_hash->fee_total;
 | 
			
		||||
 | 
			
		||||
        $payment_record = [];
 | 
			
		||||
        $payment_record['amount'] = $amount;
 | 
			
		||||
        $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER;
 | 
			
		||||
        $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD;
 | 
			
		||||
        $payment_record['transaction_reference'] = $response->transaction_id;
 | 
			
		||||
 | 
			
		||||
        $payment = $this->paytrace_driver->createPayment($payment_record, Payment::STATUS_COMPLETED);
 | 
			
		||||
 | 
			
		||||
        return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function processUnsuccessfulPayment($response)
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
        $error = $response->status_message;
 | 
			
		||||
 | 
			
		||||
        if(property_exists($response, 'approval_message') && $response->approval_message)
 | 
			
		||||
            $error .= " - {$response->approval_message}";
 | 
			
		||||
 | 
			
		||||
        $error_code = property_exists($response, 'approval_message') ? $response->approval_message : 'Undefined code';
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'response' => $response,
 | 
			
		||||
            'error' => $error,
 | 
			
		||||
            'error_code' => $error_code,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        return $this->paytrace_driver->processUnsuccessfulTransaction($data);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										234
									
								
								app/PaymentDrivers/PaytracePaymentDriver.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								app/PaymentDrivers/PaytracePaymentDriver.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,234 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * Invoice Ninja (https://invoiceninja.com).
 | 
			
		||||
 *
 | 
			
		||||
 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
			
		||||
 *
 | 
			
		||||
 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
			
		||||
 *
 | 
			
		||||
 * @license https://www.elastic.co/licensing/elastic-license
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace App\PaymentDrivers;
 | 
			
		||||
 | 
			
		||||
use App\Jobs\Util\SystemLogger;
 | 
			
		||||
use App\Models\ClientGatewayToken;
 | 
			
		||||
use App\Models\GatewayType;
 | 
			
		||||
use App\Models\Payment;
 | 
			
		||||
use App\Models\PaymentHash;
 | 
			
		||||
use App\Models\PaymentType;
 | 
			
		||||
use App\Models\SystemLog;
 | 
			
		||||
use App\PaymentDrivers\PayTrace\CreditCard;
 | 
			
		||||
use App\Utils\CurlUtils;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
 | 
			
		||||
class PaytracePaymentDriver extends BaseDriver
 | 
			
		||||
{
 | 
			
		||||
    use MakesHash;
 | 
			
		||||
    
 | 
			
		||||
    public $refundable = true; 
 | 
			
		||||
 | 
			
		||||
    public $token_billing = true; 
 | 
			
		||||
 | 
			
		||||
    public $can_authorise_credit_card = true; 
 | 
			
		||||
 | 
			
		||||
    public $gateway; 
 | 
			
		||||
 | 
			
		||||
    public $payment_method; 
 | 
			
		||||
 | 
			
		||||
    public static $methods = [
 | 
			
		||||
        GatewayType::CREDIT_CARD => CreditCard::class, //maps GatewayType => Implementation class
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYTRACE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model
 | 
			
		||||
 | 
			
		||||
    public function init()
 | 
			
		||||
    {
 | 
			
		||||
        return $this; /* This is where you boot the gateway with your auth credentials*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Returns an array of gateway types for the payment gateway */
 | 
			
		||||
    public function gatewayTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        $types = [];
 | 
			
		||||
 | 
			
		||||
            $types[] = GatewayType::CREDIT_CARD;
 | 
			
		||||
 | 
			
		||||
        return $types;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Sets the payment method initialized */
 | 
			
		||||
    public function setPaymentMethod($payment_method_id)
 | 
			
		||||
    {
 | 
			
		||||
        $class = self::$methods[$payment_method_id];
 | 
			
		||||
        $this->payment_method = new $class($this);
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function authorizeView(array $data)
 | 
			
		||||
    {
 | 
			
		||||
        return $this->payment_method->authorizeView($data); //this is your custom implementation from here
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function authorizeResponse($request)
 | 
			
		||||
    {
 | 
			
		||||
        return $this->payment_method->authorizeResponse($request);  //this is your custom implementation from here
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function processPaymentView(array $data)
 | 
			
		||||
    {
 | 
			
		||||
        return $this->payment_method->paymentView($data);  //this is your custom implementation from here
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function processPaymentResponse($request)
 | 
			
		||||
    {
 | 
			
		||||
        return $this->payment_method->paymentResponse($request); //this is your custom implementation from here
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function refund(Payment $payment, $amount, $return_client_response = false)
 | 
			
		||||
    {
 | 
			
		||||
        // $cgt = ClientGatewayToken::where('company_gateway_id', $payment->company_gateway_id)
 | 
			
		||||
        //                          ->where('gateway_type_id', $payment->gateway_type_id)
 | 
			
		||||
        //                          ->first();
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'amount' => $amount,
 | 
			
		||||
            //'customer_id' => $cgt->token,
 | 
			
		||||
            'transaction_id' => $payment->transaction_reference,
 | 
			
		||||
            'integrator_id' => '959195xd1CuC'
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $response = $this->gatewayRequest('/v1/transactions/refund/for_transaction', $data);
 | 
			
		||||
 | 
			
		||||
        if($response && $response->success)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            SystemLogger::dispatch(['server_response' => $response, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYTRACE, $this->client, $this->client->company);
 | 
			
		||||
 | 
			
		||||
                return [
 | 
			
		||||
                    'transaction_reference' => $response->transaction_id,
 | 
			
		||||
                    'transaction_response' => json_encode($response),
 | 
			
		||||
                    'success' => true,
 | 
			
		||||
                    'description' => $response->status_message,
 | 
			
		||||
                    'code' => $response->response_code,
 | 
			
		||||
                ];
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SystemLogger::dispatch(['server_response' => $response, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYTRACE, $this->client, $this->client->company);
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'transaction_reference' => null,
 | 
			
		||||
            'transaction_response' => json_encode($response),
 | 
			
		||||
            'success' => false,
 | 
			
		||||
            'description' => $response->status_message,
 | 
			
		||||
            'code' => 422,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
 | 
			
		||||
    {
 | 
			
		||||
        $amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total;
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'customer_id' => $cgt->token,
 | 
			
		||||
            'integrator_id' =>  $this->company_gateway->getConfigField('integratorId'),
 | 
			
		||||
            'amount' => $amount,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $response = $this->gatewayRequest('/v1/transactions/sale/by_customer', $data);
 | 
			
		||||
 | 
			
		||||
        if($response && $response->success)
 | 
			
		||||
        {
 | 
			
		||||
            $data = [
 | 
			
		||||
                'gateway_type_id' => $cgt->gateway_type_id,
 | 
			
		||||
                'payment_type' => PaymentType::CREDIT_CARD_OTHER,
 | 
			
		||||
                'transaction_reference' => $response->transaction_id,
 | 
			
		||||
                'amount' => $amount,
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
            $payment = $this->createPayment($data);
 | 
			
		||||
            $payment->meta = $cgt->meta;
 | 
			
		||||
            $payment->save();
 | 
			
		||||
 | 
			
		||||
            $payment_hash->payment_id = $payment->id;
 | 
			
		||||
            $payment_hash->save();
 | 
			
		||||
 | 
			
		||||
            return $payment;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $error = $response->status_message;
 | 
			
		||||
 | 
			
		||||
        if(property_exists($response, 'approval_message') && $response->approval_message)
 | 
			
		||||
            $error .= " - {$response->approval_message}";
 | 
			
		||||
 | 
			
		||||
        $data = [
 | 
			
		||||
            'response' => $response,
 | 
			
		||||
            'error' => $error,
 | 
			
		||||
            'error_code' => 500,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $this->processUnsuccessfulTransaction($data, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Helpers*/
 | 
			
		||||
    private function generateAuthHeaders()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $url = 'https://api.paytrace.com/oauth/token';
 | 
			
		||||
        $data = [
 | 
			
		||||
            'grant_type' => 'password',
 | 
			
		||||
            'username' => $this->company_gateway->getConfigField('username'),
 | 
			
		||||
            'password' => $this->company_gateway->getConfigField('password')
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $response = CurlUtils::post($url, $data, $headers = false);
 | 
			
		||||
 | 
			
		||||
        $auth_data = json_decode($response);
 | 
			
		||||
 | 
			
		||||
            $headers = [];
 | 
			
		||||
            $headers[] = 'Content-type: application/json';
 | 
			
		||||
            $headers[] = 'Authorization: Bearer '.$auth_data->access_token;
 | 
			
		||||
 | 
			
		||||
        return $headers;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAuthToken()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $headers = $this->generateAuthHeaders();
 | 
			
		||||
 | 
			
		||||
        $response = CurlUtils::post('https://api.paytrace.com/v1/payment_fields/token/create', [], $headers);
 | 
			
		||||
 | 
			
		||||
        $response = json_decode($response);
 | 
			
		||||
 | 
			
		||||
        if($response)
 | 
			
		||||
            return $response->clientKey;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function gatewayRequest($uri, $data, $headers = false)
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
        $base_url = "https://api.paytrace.com{$uri}";
 | 
			
		||||
 | 
			
		||||
        $headers = $this->generateAuthHeaders();
 | 
			
		||||
 | 
			
		||||
        $response = CurlUtils::post($base_url, json_encode($data), $headers);
 | 
			
		||||
 | 
			
		||||
        $response = json_decode($response);
 | 
			
		||||
 | 
			
		||||
        if($response)
 | 
			
		||||
            return $response;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -74,7 +74,7 @@ class Charge
 | 
			
		||||
              'confirm' => true,
 | 
			
		||||
              'description' => $description,
 | 
			
		||||
            ];
 | 
			
		||||
nlog($data);
 | 
			
		||||
 | 
			
		||||
            $response = $this->stripe->createPaymentIntent($data, $this->stripe->stripe_connect_auth);
 | 
			
		||||
            // $response = $local_stripe->paymentIntents->create($data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -84,6 +84,10 @@ return [
 | 
			
		||||
        'test_email' => env('TEST_EMAIL', 'test@example.com'),
 | 
			
		||||
        'wepay' => env('WEPAY_KEYS', ''),
 | 
			
		||||
        'braintree' => env('BRAINTREE_KEYS', ''),
 | 
			
		||||
        'paytrace' => [
 | 
			
		||||
            'username' => env('PAYTRACE_U', ''),
 | 
			
		||||
            'password' => env('PAYTRACE_P','')
 | 
			
		||||
        ],
 | 
			
		||||
    ],
 | 
			
		||||
    'contact' => [
 | 
			
		||||
        'email' => env('MAIL_FROM_ADDRESS'),
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,39 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use App\Models\Gateway;
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
 | 
			
		||||
class ActivatePaytracePaymentDriver extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function up()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        if($paytrace = Gateway::find(46))
 | 
			
		||||
        {
 | 
			
		||||
            $fields = json_decode($paytrace->fields);
 | 
			
		||||
            $fields->integratorId = "";
 | 
			
		||||
 | 
			
		||||
            $paytrace->fields = json_encode($fields);
 | 
			
		||||
            $paytrace->provider = 'Paytrace';
 | 
			
		||||
            $paytrace->visible = true;
 | 
			
		||||
            $paytrace->save();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function down()
 | 
			
		||||
    {
 | 
			
		||||
        //
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -70,7 +70,7 @@ class PaymentLibrariesSeeder extends Seeder
 | 
			
		||||
            ['id' => 43, 'name' => 'Fasapay', 'provider' => 'Fasapay', 'key' => '1b2cef0e8c800204a29f33953aaf3360', 'fields' => ''],
 | 
			
		||||
            ['id' => 44, 'name' => 'Komoju', 'provider' => 'Komoju', 'key' => '7ea2d40ecb1eb69ef8c3d03e5019028a', 'fields' => '{"apiKey":"","accountId":"","paymentMethod":"credit_card","testMode":false,"locale":"en"}'],
 | 
			
		||||
            ['id' => 45, 'name' => 'Paysafecard', 'provider' => 'Paysafecard', 'key' => '70ab90cd6c5c1ab13208b3cef51c0894', 'fields' => '{"username":"","password":"","testMode":false}'],
 | 
			
		||||
            ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace_CreditCard', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'],
 | 
			
		||||
            ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","integratorId":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'],
 | 
			
		||||
            ['id' => 47, 'name' => 'Secure Trading', 'provider' => 'SecureTrading', 'key' => '231cb401487b9f15babe04b1ac4f7a27', 'fields' => '{"siteReference":"","username":"","password":"","applyThreeDSecure":false,"accountType":"ECOM"}'],
 | 
			
		||||
            ['id' => 48, 'name' => 'SecPay', 'provider' => 'SecPay', 'key' => 'bad8699d581d9fa040e59c0bb721a76c', 'fields' => '{"mid":"","vpnPswd":"","remotePswd":"","usageType":"","confirmEmail":"","testStatus":"true","mailCustomer":"true","additionalOptions":""}'],
 | 
			
		||||
            ['id' => 49, 'name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false, 'sort_order' => 3, 'key' => '8fdeed552015b3c7b44ed6c8ebd9e992', 'fields' => '{"accountId":"","accessToken":"","type":"goods","testMode":false,"feePayer":"payee"}'],
 | 
			
		||||
@ -96,7 +96,7 @@ class PaymentLibrariesSeeder extends Seeder
 | 
			
		||||
 | 
			
		||||
        Gateway::query()->update(['visible' => 0]);
 | 
			
		||||
 | 
			
		||||
        Gateway::whereIn('id', [1,15,20,39,55,50])->update(['visible' => 1]);
 | 
			
		||||
        Gateway::whereIn('id', [1,15,20,39,46,55,50])->update(['visible' => 1]);
 | 
			
		||||
 | 
			
		||||
        if (Ninja::isHosted()) {
 | 
			
		||||
            Gateway::whereIn('id', [20])->update(['visible' => 0]);
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,145 @@
 | 
			
		||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
 | 
			
		||||
 | 
			
		||||
@section('gateway_head')
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@section('gateway_content')
 | 
			
		||||
    
 | 
			
		||||
    @if(!Request::isSecure())
 | 
			
		||||
        <p class="alert alert-failure">{{ ctrans('texts.https_required') }}</p>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <div class="alert alert-failure mb-4" hidden id="errors"></div>
 | 
			
		||||
    <form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}"  method="post" id="server_response">
 | 
			
		||||
        @csrf
 | 
			
		||||
 | 
			
		||||
    <div class="w-screen items-center">
 | 
			
		||||
 | 
			
		||||
        <div id='pt_hpf_form'><!--iframe sensitive data payment fields inserted here--></div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
 | 
			
		||||
    <input type="txt" id=HPF_Token name= HPF_Token hidden>
 | 
			
		||||
    <input type="txt" id=enc_key name= enc_key hidden>
 | 
			
		||||
 | 
			
		||||
    <div class="bg-white px-4 py-5 flex justify-end">
 | 
			
		||||
        <button
 | 
			
		||||
            type="submit"
 | 
			
		||||
            id="{{ $id ?? 'pay-now' }}"
 | 
			
		||||
            class="button button-primary bg-primary {{ $class ?? '' }}">
 | 
			
		||||
            <span>{{ ctrans('texts.add_payment_method') }}</span>
 | 
			
		||||
        </button>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    </form>
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@section('gateway_footer')
 | 
			
		||||
 | 
			
		||||
<script src='https://protect.paytrace.com/js/protect.min.js'></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
  // Minimal Protect.js setup call
 | 
			
		||||
PTPayment.setup({
 | 
			
		||||
  styles:
 | 
			
		||||
  {
 | 
			
		||||
   'code': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'dotted',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'100px'
 | 
			
		||||
 },
 | 
			
		||||
   'cc': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'solid',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'300px'
 | 
			
		||||
 },
 | 
			
		||||
   'exp': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'dashed',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'85px',
 | 
			
		||||
    'type':'dropdown'
 | 
			
		||||
  }
 | 
			
		||||
 },
 | 
			
		||||
  authorization: { 'clientKey': "{!! $client_key !!}" }
 | 
			
		||||
}).then(function(instance){
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    PTPayment.getControl("securityCode").label.text("{!! ctrans('texts.cvv')!!}");
 | 
			
		||||
    PTPayment.getControl("creditCard").label.text("{!! ctrans('texts.card_number')!!}");
 | 
			
		||||
    PTPayment.getControl("expiration").label.text("{!! ctrans('texts.expires')!!}");
 | 
			
		||||
    //PTPayment.style({'cc': {'label_color': 'red'}});
 | 
			
		||||
    //PTPayment.style({'code': {'label_color': 'red'}});
 | 
			
		||||
    //PTPayment.style({'exp': {'label_color': 'red'}});
 | 
			
		||||
    //PTPayment.style({'exp':{'type':'dropdown'}});
 | 
			
		||||
 | 
			
		||||
    //PTPayment.theme('horizontal');
 | 
			
		||||
    // this can be any event we chose. We will use the submit event and stop any default event handling and prevent event handling bubbling.
 | 
			
		||||
    document.getElementById("server_response").addEventListener("submit",function(e){
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    e.stopPropagation();
 | 
			
		||||
 | 
			
		||||
    // To trigger the validation of sensitive data payment fields within the iframe before calling the tokenization process:
 | 
			
		||||
    PTPayment.validate(function(validationErrors) {
 | 
			
		||||
 | 
			
		||||
    if (validationErrors.length >= 1) {
 | 
			
		||||
 | 
			
		||||
        let errors = document.getElementById('errors');
 | 
			
		||||
 | 
			
		||||
        errors.textContent = '';
 | 
			
		||||
        errors.textContent = validationErrors[0].description;
 | 
			
		||||
        errors.hidden = false;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
     // no error so tokenize
 | 
			
		||||
     instance.process()
 | 
			
		||||
     .then( (r) => {
 | 
			
		||||
        submitPayment(r);
 | 
			
		||||
        }, (err) => {
 | 
			
		||||
        handleError(err);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function handleError(err){
 | 
			
		||||
    document.write(JSON.stringify(err));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function submitPayment(r){
 | 
			
		||||
 | 
			
		||||
  var hpf_token = document.getElementById("HPF_Token");
 | 
			
		||||
  var enc_key = document.getElementById("enc_key");
 | 
			
		||||
  hpf_token.value = r.message.hpf_token;
 | 
			
		||||
  enc_key.value = r.message.enc_key;
 | 
			
		||||
 | 
			
		||||
  document.getElementById("server_response").submit();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@endsection
 | 
			
		||||
							
								
								
									
										207
									
								
								resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,207 @@
 | 
			
		||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ctrans('texts.payment_type_credit_card')])
 | 
			
		||||
 | 
			
		||||
@section('gateway_head')
 | 
			
		||||
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@section('gateway_content')
 | 
			
		||||
    <form action="{{ route('client.payments.response') }}" method="post" id="server_response">
 | 
			
		||||
        @csrf
 | 
			
		||||
        <input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
 | 
			
		||||
        <input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
 | 
			
		||||
        <input type="hidden" name="payment_method_id" value="1">
 | 
			
		||||
        <input type="hidden" name="token" id="token"/>
 | 
			
		||||
        <input type="hidden" name="store_card" id="store_card"/>
 | 
			
		||||
        <input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
 | 
			
		||||
        <input type="txt" id=HPF_Token name= HPF_Token hidden>
 | 
			
		||||
        <input type="txt" id=enc_key name= enc_key hidden>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <div class="alert alert-failure mb-4" hidden id="errors"></div>
 | 
			
		||||
 | 
			
		||||
    @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
 | 
			
		||||
        {{ ctrans('texts.credit_card') }}
 | 
			
		||||
    @endcomponent
 | 
			
		||||
 | 
			
		||||
    @include('portal.ninja2020.gateways.includes.payment_details')
 | 
			
		||||
 | 
			
		||||
    @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
 | 
			
		||||
        @if(count($tokens) > 0)
 | 
			
		||||
            @foreach($tokens as $token)
 | 
			
		||||
                <label class="mr-4">
 | 
			
		||||
                    <input
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        data-token="{{ $token->hashed_id }}"
 | 
			
		||||
                        name="payment-type"
 | 
			
		||||
                        class="form-radio cursor-pointer toggle-payment-with-token"/>
 | 
			
		||||
                    <span class="ml-1 cursor-pointer">{{ optional($token->meta)->last4 }}</span>
 | 
			
		||||
                </label>
 | 
			
		||||
            @endforeach
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        <label>
 | 
			
		||||
            <input
 | 
			
		||||
                type="radio"
 | 
			
		||||
                id="toggle-payment-with-credit-card"
 | 
			
		||||
                class="form-radio cursor-pointer"
 | 
			
		||||
                name="payment-type"
 | 
			
		||||
                checked/>
 | 
			
		||||
            <span class="ml-1 cursor-pointer">{{ __('texts.new_card') }}</span>
 | 
			
		||||
        </label>
 | 
			
		||||
    @endcomponent
 | 
			
		||||
 | 
			
		||||
    @include('portal.ninja2020.gateways.includes.save_card')
 | 
			
		||||
 | 
			
		||||
    <div class="w-screen items-center" id="paytrace--credit-card-container">
 | 
			
		||||
 | 
			
		||||
        <div id='pt_hpf_form'><!--iframe sensitive data payment fields inserted here--></div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    @include('portal.ninja2020.gateways.includes.pay_now', ['type' => 'submit'])
 | 
			
		||||
    </form>
 | 
			
		||||
@endsection
 | 
			
		||||
 | 
			
		||||
@section('gateway_footer')
 | 
			
		||||
 | 
			
		||||
<script src='https://protect.paytrace.com/js/protect.min.js'></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
    let token_payment = true;
 | 
			
		||||
 | 
			
		||||
    Array
 | 
			
		||||
    .from(document.getElementsByClassName('toggle-payment-with-token'))
 | 
			
		||||
    .forEach((element) => element.addEventListener('click', (e) => {
 | 
			
		||||
        document
 | 
			
		||||
            .getElementById('save-card--container').style.display = 'none';
 | 
			
		||||
        document
 | 
			
		||||
            .getElementById('paytrace--credit-card-container').style.display = 'none';
 | 
			
		||||
 | 
			
		||||
        document
 | 
			
		||||
            .getElementById('token').value = e.target.dataset.token;
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    let payWithCreditCardToggle = document.getElementById('toggle-payment-with-credit-card');
 | 
			
		||||
 | 
			
		||||
    if (payWithCreditCardToggle) {
 | 
			
		||||
        payWithCreditCardToggle
 | 
			
		||||
            .addEventListener('click', () => {
 | 
			
		||||
                document
 | 
			
		||||
                    .getElementById('save-card--container').style.display = 'grid';
 | 
			
		||||
                document
 | 
			
		||||
                    .getElementById('paytrace--credit-card-container').style.display = 'grid';
 | 
			
		||||
 | 
			
		||||
                document
 | 
			
		||||
                    .getElementById('token').value = null;
 | 
			
		||||
                    token_payment = false;
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var tokens = document.getElementsByClassName('toggle-payment-with-token');
 | 
			
		||||
    tokens[0].click();
 | 
			
		||||
 | 
			
		||||
  // Minimal Protect.js setup call
 | 
			
		||||
PTPayment.setup({
 | 
			
		||||
  styles:
 | 
			
		||||
  {
 | 
			
		||||
   'code': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'dotted',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'100px'
 | 
			
		||||
 },
 | 
			
		||||
   'cc': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'solid',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'300px'
 | 
			
		||||
 },
 | 
			
		||||
   'exp': {
 | 
			
		||||
    'font_color':'#5D99CA',
 | 
			
		||||
    'border_color':'#EF9F6D',
 | 
			
		||||
    'label_color':'#EF9F6D',
 | 
			
		||||
    'label_size':'20px',
 | 
			
		||||
    'background_color':'white',
 | 
			
		||||
    'border_style':'dashed',
 | 
			
		||||
    'font_size':'15pt',
 | 
			
		||||
    'height':'30px',
 | 
			
		||||
    'width':'85px',
 | 
			
		||||
    'type':'dropdown'
 | 
			
		||||
  }
 | 
			
		||||
 },
 | 
			
		||||
  authorization: { 'clientKey': "{!! $client_key !!}" }
 | 
			
		||||
}).then(function(instance){
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    PTPayment.getControl("securityCode").label.text("{!! ctrans('texts.cvv')!!}");
 | 
			
		||||
    PTPayment.getControl("creditCard").label.text("{!! ctrans('texts.card_number')!!}");
 | 
			
		||||
    PTPayment.getControl("expiration").label.text("{!! ctrans('texts.expires')!!}");
 | 
			
		||||
 | 
			
		||||
    document.getElementById("server_response").addEventListener("submit",function(e){
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    e.stopPropagation();
 | 
			
		||||
 | 
			
		||||
    PTPayment.validate(function(validationErrors) {
 | 
			
		||||
 | 
			
		||||
    if (validationErrors.length >= 1 && !token_payment) {
 | 
			
		||||
        let errors = document.getElementById('errors');
 | 
			
		||||
 | 
			
		||||
        errors.textContent = '';
 | 
			
		||||
        errors.textContent = validationErrors[0].description;
 | 
			
		||||
        errors.hidden = false;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
     // no error so tokenize
 | 
			
		||||
     if(token_payment){
 | 
			
		||||
 | 
			
		||||
        tokenPayment();
 | 
			
		||||
     } 
 | 
			
		||||
     
 | 
			
		||||
     instance.process()
 | 
			
		||||
     .then( (r) => {
 | 
			
		||||
        submitPayment(r);
 | 
			
		||||
        }, (err) => {
 | 
			
		||||
        handleError(err);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function handleError(err){
 | 
			
		||||
    console.log(err);
 | 
			
		||||
    document.write(JSON.stringify(err));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function submitPayment(r){
 | 
			
		||||
 | 
			
		||||
  var hpf_token = document.getElementById("HPF_Token");
 | 
			
		||||
  var enc_key = document.getElementById("enc_key");
 | 
			
		||||
  hpf_token.value = r.message.hpf_token;
 | 
			
		||||
  enc_key.value = r.message.enc_key;
 | 
			
		||||
 | 
			
		||||
  document.getElementById("server_response").submit();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function tokenPayment(){
 | 
			
		||||
 | 
			
		||||
      document.getElementById("server_response").submit();
 | 
			
		||||
      return false;
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@endsection
 | 
			
		||||
							
								
								
									
										29
									
								
								resources/views/vendor/livewire/simple-bootstrap.blade.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								resources/views/vendor/livewire/simple-bootstrap.blade.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
<div>
 | 
			
		||||
    @if ($paginator->hasPages())
 | 
			
		||||
        <nav>
 | 
			
		||||
            <ul class="pagination">
 | 
			
		||||
                {{-- Previous Page Link --}}
 | 
			
		||||
                @if ($paginator->onFirstPage())
 | 
			
		||||
                    <li class="page-item disabled" aria-disabled="true">
 | 
			
		||||
                        <span class="page-link">@lang('pagination.previous')</span>
 | 
			
		||||
                    </li>
 | 
			
		||||
                @else
 | 
			
		||||
                    <li class="page-item">
 | 
			
		||||
                        <button type="button" class="page-link" wire:click="previousPage" wire:loading.attr="disabled" rel="prev">@lang('pagination.previous')</button>
 | 
			
		||||
                    </li>
 | 
			
		||||
                @endif
 | 
			
		||||
 | 
			
		||||
                {{-- Next Page Link --}}
 | 
			
		||||
                @if ($paginator->hasMorePages())
 | 
			
		||||
                    <li class="page-item">
 | 
			
		||||
                        <button type="button" class="page-link" wire:click="nextPage" wire:loading.attr="disabled" rel="next">@lang('pagination.next')</button>
 | 
			
		||||
                    </li>
 | 
			
		||||
                @else
 | 
			
		||||
                    <li class="page-item disabled" aria-disabled="true">
 | 
			
		||||
                        <span class="page-link">@lang('pagination.next')</span>
 | 
			
		||||
                    </li>
 | 
			
		||||
                @endif
 | 
			
		||||
            </ul>
 | 
			
		||||
        </nav>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user