mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 04:47:30 -04:00 
			
		
		
		
	
						commit
						dac9af20ab
					
				| @ -22,7 +22,7 @@ class ExpenseCategoryFactory | |||||||
|         $expense->company_id = $company_id; |         $expense->company_id = $company_id; | ||||||
|         $expense->name = ''; |         $expense->name = ''; | ||||||
|         $expense->is_deleted = false; |         $expense->is_deleted = false; | ||||||
|         $expense->color = '#fff'; |         $expense->color = ''; | ||||||
|          |          | ||||||
|         return $expense; |         return $expense; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ class TaskStatusFactory | |||||||
|         $task_status->user_id = $user_id; |         $task_status->user_id = $user_id; | ||||||
|         $task_status->company_id = $company_id; |         $task_status->company_id = $company_id; | ||||||
|         $task_status->name = ''; |         $task_status->name = ''; | ||||||
|         $task_status->color = '#fff'; |         $task_status->color = ''; | ||||||
|         $task_status->status_order = 9999; |         $task_status->status_order = 9999; | ||||||
|          |          | ||||||
|         return $task_status; |         return $task_status; | ||||||
|  | |||||||
| @ -474,6 +474,10 @@ class CompanyController extends BaseController | |||||||
|      */ |      */ | ||||||
|     public function destroy(DestroyCompanyRequest $request, Company $company) |     public function destroy(DestroyCompanyRequest $request, Company $company) | ||||||
|     { |     { | ||||||
|  | 
 | ||||||
|  |         if(Ninja::isHosted() && config('ninja.ninja_default_company_id') == $company->id) | ||||||
|  |             return response()->json(['message' => 'Cannot purge this company'], 400); | ||||||
|  |          | ||||||
|         $company_count = $company->account->companies->count(); |         $company_count = $company->account->companies->count(); | ||||||
|         $account = $company->account; |         $account = $company->account; | ||||||
|         $account_key = $account->key; |         $account_key = $account->key; | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ use App\Utils\CurlUtils; | |||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use Illuminate\Http\Response; | use Illuminate\Http\Response; | ||||||
| use stdClass; | use stdClass; | ||||||
|  | use Carbon\Carbon; | ||||||
| 
 | 
 | ||||||
| class LicenseController extends BaseController | class LicenseController extends BaseController | ||||||
| { | { | ||||||
| @ -152,7 +153,7 @@ class LicenseController extends BaseController | |||||||
|     { |     { | ||||||
|         $account = auth()->user()->company()->account; |         $account = auth()->user()->company()->account; | ||||||
| 
 | 
 | ||||||
|         if($account->plan == 'white_label' && $account->plan_expires->lt(now())){ |         if($account->plan == 'white_label' && Carbon::parse($account->plan_expires)->lt(now())){ | ||||||
|             $account->plan = null; |             $account->plan = null; | ||||||
|             $account->plan_expires = null; |             $account->plan_expires = null; | ||||||
|             $account->save(); |             $account->save(); | ||||||
|  | |||||||
| @ -82,6 +82,9 @@ class MigrationController extends BaseController | |||||||
|      */ |      */ | ||||||
|     public function purgeCompany(Company $company) |     public function purgeCompany(Company $company) | ||||||
|     { |     { | ||||||
|  |         if(Ninja::isHosted() && config('ninja.ninja_default_company_id') == $company->id) | ||||||
|  |             return response()->json(['message' => 'Cannot purge this company'], 400); | ||||||
|  | 
 | ||||||
|         $account = $company->account; |         $account = $company->account; | ||||||
|         $company_id = $company->id; |         $company_id = $company->id; | ||||||
| 
 | 
 | ||||||
| @ -102,6 +105,9 @@ class MigrationController extends BaseController | |||||||
| 
 | 
 | ||||||
|     private function purgeCompanyWithForceFlag(Company $company) |     private function purgeCompanyWithForceFlag(Company $company) | ||||||
|     { |     { | ||||||
|  |         if(Ninja::isHosted() && config('ninja.ninja_default_company_id') == $company->id) | ||||||
|  |             return response()->json(['message' => 'Cannot purge this company'], 400); | ||||||
|  | 
 | ||||||
|         $account = $company->account; |         $account = $company->account; | ||||||
|         $company_id = $company->id; |         $company_id = $company->id; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -0,0 +1,36 @@ | |||||||
|  | <?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\Http\Controllers; | ||||||
|  | 
 | ||||||
|  | use App\Http\Requests\Payments\PaymentNotificationWebhookRequest; | ||||||
|  | use App\Libraries\MultiDB; | ||||||
|  | use App\Models\Client; | ||||||
|  | use App\Models\CompanyGateway; | ||||||
|  | use App\Utils\Traits\MakesHash; | ||||||
|  | use Auth; | ||||||
|  | 
 | ||||||
|  | class PaymentNotificationWebhookController extends Controller | ||||||
|  | { | ||||||
|  |     use MakesHash; | ||||||
|  |      | ||||||
|  |     public function __invoke(PaymentNotificationWebhookRequest $request, string $company_key, string $company_gateway_id, string $client_hash) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $company_gateway = CompanyGateway::find($this->decodePrimaryKey($company_gateway_id)); | ||||||
|  |         $client = Client::find($this->decodePrimaryKey($client_hash)); | ||||||
|  | 
 | ||||||
|  |         return $company_gateway | ||||||
|  |                 ->driver($client) | ||||||
|  |                 ->processWebhookRequest($request); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -30,17 +30,22 @@ class UrlSetDb | |||||||
|      */ |      */ | ||||||
|     public function handle($request, Closure $next) |     public function handle($request, Closure $next) | ||||||
|     { |     { | ||||||
|  |          | ||||||
|         if (config('ninja.db.multi_db_enabled')) { |         if (config('ninja.db.multi_db_enabled')) { | ||||||
|             $hashids = new Hashids('', 10); //decoded output is _always_ an array.
 |             $hashids = new Hashids(config('ninja.hash_salt'), 10); | ||||||
| 
 | 
 | ||||||
|             //parse URL hash and set DB
 |             //parse URL hash and set DB
 | ||||||
|             $segments = explode('-', $request->route('confirmation_code')); |             $segments = explode('-', $request->route('confirmation_code')); | ||||||
| 
 | 
 | ||||||
|  |             if(!is_array($segments)) | ||||||
|  |                 return response()->json(['message' => 'Invalid confirmation code'], 403); | ||||||
|  | 
 | ||||||
|             $hashed_db = $hashids->decode($segments[0]); |             $hashed_db = $hashids->decode($segments[0]); | ||||||
| 
 | 
 | ||||||
|             MultiDB::setDB(MultiDB::DB_PREFIX.str_pad($hashed_db[0], 2, '0', STR_PAD_LEFT)); |             MultiDB::setDB(MultiDB::DB_PREFIX.str_pad($hashed_db[0], 2, '0', STR_PAD_LEFT)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return $next($request); |         return $next($request); | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ class StoreExpenseRequest extends Request | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(array_key_exists('color', $input) && is_null($input['color'])) |         if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|             $input['color'] = '#fff'; |             $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ class StoreExpenseCategoryRequest extends Request | |||||||
|         $input = $this->decodePrimaryKeys($input); |         $input = $this->decodePrimaryKeys($input); | ||||||
| 
 | 
 | ||||||
|         if(array_key_exists('color', $input) && is_null($input['color'])) |         if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|             $input['color'] = '#fff'; |             $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ class UpdateExpenseCategoryRequest extends Request | |||||||
|         $input = $this->all(); |         $input = $this->all(); | ||||||
| 
 | 
 | ||||||
|             if(array_key_exists('color', $input) && is_null($input['color'])) |             if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|                 $input['color'] = '#fff'; |                 $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -0,0 +1,42 @@ | |||||||
|  | <?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\Http\Requests\Payments; | ||||||
|  | 
 | ||||||
|  | use App\Http\Requests\Request; | ||||||
|  | use App\Libraries\MultiDB; | ||||||
|  | use App\Models\Client; | ||||||
|  | use App\Models\Company; | ||||||
|  | use App\Models\CompanyGateway; | ||||||
|  | use App\Models\Payment; | ||||||
|  | use App\Models\PaymentHash; | ||||||
|  | use App\Utils\Traits\MakesHash; | ||||||
|  | 
 | ||||||
|  | class PaymentNotificationWebhookRequest extends Request | ||||||
|  | { | ||||||
|  |     use MakesHash; | ||||||
|  | 
 | ||||||
|  |     public function authorize() | ||||||
|  |     { | ||||||
|  |         MultiDB::findAndSetDbByCompanyKey($this->company_key); | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function rules() | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             //
 | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -51,7 +51,7 @@ class StoreProjectRequest extends Request | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         if(array_key_exists('color', $input) && is_null($input['color'])) |         if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|             $input['color'] = '#fff'; |             $input['color'] = ''; | ||||||
|          |          | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ class UpdateProjectRequest extends Request | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(array_key_exists('color', $input) && is_null($input['color'])) |         if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|             $input['color'] = '#fff'; |             $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ class UpdateTaskRequest extends Request | |||||||
|         } |         } | ||||||
|          |          | ||||||
|         if(array_key_exists('color', $input) && is_null($input['color'])) |         if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|             $input['color'] = '#fff'; |             $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ class StoreTaskStatusRequest extends Request | |||||||
|         $input = $this->all(); |         $input = $this->all(); | ||||||
| 
 | 
 | ||||||
|             if(array_key_exists('color', $input) && is_null($input['color'])) |             if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|                 $input['color'] = '#fff'; |                 $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ class UpdateTaskStatusRequest extends Request | |||||||
|         $input = $this->all(); |         $input = $this->all(); | ||||||
| 
 | 
 | ||||||
|             if(array_key_exists('color', $input) && is_null($input['color'])) |             if(array_key_exists('color', $input) && is_null($input['color'])) | ||||||
|                 $input['color'] = '#fff'; |                 $input['color'] = ''; | ||||||
| 
 | 
 | ||||||
|         $this->replace($input); |         $this->replace($input); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; | |||||||
| use Illuminate\Foundation\Bus\Dispatchable; | use Illuminate\Foundation\Bus\Dispatchable; | ||||||
| use Illuminate\Queue\InteractsWithQueue; | use Illuminate\Queue\InteractsWithQueue; | ||||||
| use Illuminate\Queue\SerializesModels; | use Illuminate\Queue\SerializesModels; | ||||||
|  | use Carbon\Carbon; | ||||||
| 
 | 
 | ||||||
| class VersionCheck implements ShouldQueue | class VersionCheck implements ShouldQueue | ||||||
| { | { | ||||||
| @ -49,7 +50,7 @@ class VersionCheck implements ShouldQueue | |||||||
|             if(!$account) |             if(!$account) | ||||||
|                 return; |                 return; | ||||||
| 
 | 
 | ||||||
|             if($account->plan == 'white_label' && $account->plan_expires && $account->plan_expires->lt(now())){ |             if($account->plan == 'white_label' && $account->plan_expires && Carbon::parse($account->plan_expires)->lt(now())){ | ||||||
|                 $account->plan = null; |                 $account->plan = null; | ||||||
|                 $account->plan_expires = null; |                 $account->plan_expires = null; | ||||||
|                 $account->save(); |                 $account->save(); | ||||||
|  | |||||||
| @ -71,7 +71,6 @@ class PaymentNotification implements ShouldQueue | |||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         /*Google Analytics Track Revenue*/ |         /*Google Analytics Track Revenue*/ | ||||||
|         if (isset($payment->company->google_analytics_key)) { |         if (isset($payment->company->google_analytics_key)) { | ||||||
|             $this->trackRevenue($event); |             $this->trackRevenue($event); | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ class Account extends BaseModel | |||||||
|         'promo_expires', |         'promo_expires', | ||||||
|         'discount_expires', |         'discount_expires', | ||||||
|         'trial_started', |         'trial_started', | ||||||
|         'plan_expires' |         // 'plan_expires'
 | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     const PLAN_FREE = 'free'; |     const PLAN_FREE = 'free'; | ||||||
| @ -120,6 +120,11 @@ class Account extends BaseModel | |||||||
|         return $this->hasMany(CompanyUser::class); |         return $this->hasMany(CompanyUser::class); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function owner() | ||||||
|  |     { | ||||||
|  |         return $this->hasMany(CompanyUser::class)->where('is_owner', true)->first() ? $this->hasMany(CompanyUser::class)->where('is_owner', true)->first()->user : false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public function getPlan() |     public function getPlan() | ||||||
|     { |     { | ||||||
|         return $this->plan ?: ''; |         return $this->plan ?: ''; | ||||||
|  | |||||||
| @ -371,6 +371,11 @@ class CompanyGateway extends BaseModel | |||||||
|         return $fee; |         return $fee; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function webhookUrl() | ||||||
|  |     { | ||||||
|  |         return route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $this->hashed_id]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * we need to average out the gateway fees across all the invoices |      * we need to average out the gateway fees across all the invoices | ||||||
|      * so lets iterate. |      * so lets iterate. | ||||||
| @ -412,4 +417,6 @@ class CompanyGateway extends BaseModel | |||||||
|         return $this |         return $this | ||||||
|             ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); |             ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,6 +21,10 @@ class UserPresenter extends EntityPresenter | |||||||
|      */ |      */ | ||||||
|     public function name() |     public function name() | ||||||
|     { |     { | ||||||
|  | 
 | ||||||
|  |         if(!$this->entity) | ||||||
|  |             return "No User Object Available"; | ||||||
|  |          | ||||||
|         $first_name = isset($this->entity->first_name) ? $this->entity->first_name : ''; |         $first_name = isset($this->entity->first_name) ? $this->entity->first_name : ''; | ||||||
|         $last_name = isset($this->entity->last_name) ? $this->entity->last_name : ''; |         $last_name = isset($this->entity->last_name) ? $this->entity->last_name : ''; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -67,6 +67,7 @@ class SystemLog extends Model | |||||||
|     const TYPE_CUSTOM = 306; |     const TYPE_CUSTOM = 306; | ||||||
|     const TYPE_BRAINTREE = 307; |     const TYPE_BRAINTREE = 307; | ||||||
|     const TYPE_WEPAY = 309; |     const TYPE_WEPAY = 309; | ||||||
|  |     const TYPE_PAYFAST = 310; | ||||||
|      |      | ||||||
| 
 | 
 | ||||||
|     const TYPE_QUOTA_EXCEEDED = 400; |     const TYPE_QUOTA_EXCEEDED = 400; | ||||||
|  | |||||||
| @ -548,6 +548,15 @@ class BaseDriver extends AbstractPaymentDriver | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function genericWebhookUrl() | ||||||
|  |     { | ||||||
|  |         return route('payment_notification_webhook', [ | ||||||
|  |             'company_key' => $this->client->company->company_key,  | ||||||
|  |             'company_gateway_id' => $this->encodePrimaryKey($this->company_gateway->id),  | ||||||
|  |             'client' => $this->encodePrimaryKey($this->client->id), | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* Performs an extra iterate on the gatewayTypes() array and passes back only the enabled gateways*/ |     /* Performs an extra iterate on the gatewayTypes() array and passes back only the enabled gateways*/ | ||||||
|     public function gatewayTypeEnabled($type) |     public function gatewayTypeEnabled($type) | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
| 
 | 
 | ||||||
| namespace App\PaymentDrivers; | namespace App\PaymentDrivers; | ||||||
| 
 | 
 | ||||||
|  | use App\Http\Requests\Payments\PaymentWebhookRequest; | ||||||
| use App\Models\ClientGatewayToken; | use App\Models\ClientGatewayToken; | ||||||
| use App\Models\GatewayType; | use App\Models\GatewayType; | ||||||
| use App\Models\Payment; | use App\Models\Payment; | ||||||
| @ -39,6 +40,22 @@ class DriverTemplate extends BaseDriver | |||||||
| 
 | 
 | ||||||
|     const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model
 |     const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //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) |     public function setPaymentMethod($payment_method_id) | ||||||
|     { |     { | ||||||
|         $class = self::$methods[$payment_method_id]; |         $class = self::$methods[$payment_method_id]; | ||||||
| @ -75,4 +92,8 @@ class DriverTemplate extends BaseDriver | |||||||
|     { |     { | ||||||
|         return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
 |         return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) | ||||||
|  |     { | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										282
									
								
								app/PaymentDrivers/PayFast/CreditCard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								app/PaymentDrivers/PayFast/CreditCard.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,282 @@ | |||||||
|  | <?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\PayFast; | ||||||
|  | 
 | ||||||
|  | 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\Payment; | ||||||
|  | use App\Models\PaymentHash; | ||||||
|  | use App\Models\PaymentType; | ||||||
|  | use App\Models\SystemLog; | ||||||
|  | use App\PaymentDrivers\PayFastPaymentDriver; | ||||||
|  | use Illuminate\Http\Request; | ||||||
|  | use Illuminate\Support\Facades\Cache; | ||||||
|  | use Illuminate\Support\Str; | ||||||
|  | 
 | ||||||
|  | class CreditCard | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public $payfast; | ||||||
|  | 
 | ||||||
|  |     public function __construct(PayFastPaymentDriver $payfast) | ||||||
|  |     { | ||||||
|  |         $this->payfast = $payfast; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |         $data = array(); | ||||||
|  |         $data['merchant_id'] = $this->getMerchantId(); | ||||||
|  |         $data['merchant_key'] = $this->getMerchantKey(); | ||||||
|  |         $data['return_url'] = $this->getReturnUrl(); | ||||||
|  |         $data['cancel_url'] = $this->getCancelUrl(); | ||||||
|  |         $data['notify_url'] = $this->getNotifyUrl(); | ||||||
|  | 
 | ||||||
|  |         if ($this->getCard()) { | ||||||
|  |             $data['name_first'] = $this->getCard()->getFirstName(); | ||||||
|  |             $data['name_last'] = $this->getCard()->getLastName(); | ||||||
|  |             $data['email_address'] = $this->getCard()->getEmail(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $data['m_payment_id'] = $this->getTransactionId(); | ||||||
|  |         $data['amount'] = $this->getAmount(); | ||||||
|  |         $data['item_name'] = $this->getDescription(); | ||||||
|  |         $data['custom_int1'] = $this->getCustomInt1(); | ||||||
|  |         $data['custom_int2'] = $this->getCustomInt2(); | ||||||
|  |         $data['custom_int3'] = $this->getCustomInt3(); | ||||||
|  |         $data['custom_int4'] = $this->getCustomInt4(); | ||||||
|  |         $data['custom_int5'] = $this->getCustomInt5(); | ||||||
|  |         $data['custom_str1'] = $this->getCustomStr1(); | ||||||
|  |         $data['custom_str2'] = $this->getCustomStr2(); | ||||||
|  |         $data['custom_str3'] = $this->getCustomStr3(); | ||||||
|  |         $data['custom_str4'] = $this->getCustomStr4(); | ||||||
|  |         $data['custom_str5'] = $this->getCustomStr5(); | ||||||
|  | 
 | ||||||
|  |         if ($this->getPaymentMethod()) { | ||||||
|  |             $data['payment_method'] = $this->getPaymentMethod(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (1 == $this->getSubscriptionType()) { | ||||||
|  |             $data['subscription_type'] = $this->getSubscriptionType(); | ||||||
|  |             $data['billing_date'] = $this->getBillingDate(); | ||||||
|  |             $data['recurring_amount'] = $this->getRecurringAmount(); | ||||||
|  |             $data['frequency'] = $this->getFrequency(); | ||||||
|  |             $data['cycles'] = $this->getCycles(); | ||||||
|  |         } | ||||||
|  |         if (2 == $this->getSubscriptionType()) { | ||||||
|  |             $data['subscription_type'] = $this->getSubscriptionType(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $data['passphrase'] = $this->getParameter('passphrase'); 123456789012aV | ||||||
|  |         $data['signature'] = $this->generateSignature($data); | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  |     public function authorizeView($data) | ||||||
|  |     { | ||||||
|  |         $hash = Str::random(32); | ||||||
|  |          | ||||||
|  |         Cache::put($hash, 'cc_auth', 300); | ||||||
|  | 
 | ||||||
|  |         $data = [ | ||||||
|  |             'merchant_id' => $this->payfast->company_gateway->getConfigField('merchantId'), | ||||||
|  |             'merchant_key' => $this->payfast->company_gateway->getConfigField('merchantKey'), | ||||||
|  |             'return_url' => route('client.payment_methods.index'), | ||||||
|  |             'cancel_url' => route('client.payment_methods.index'), | ||||||
|  |             'notify_url' => $this->payfast->genericWebhookUrl(), | ||||||
|  |             'm_payment_id' => $hash, | ||||||
|  |             'amount' => 5, | ||||||
|  |             'item_name' => 'pre-auth', | ||||||
|  |             'item_description' => 'Credit Card Pre Authorization', | ||||||
|  |             'subscription_type' => 2, | ||||||
|  |             'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'), | ||||||
|  |         ];         | ||||||
|  | 
 | ||||||
|  |         $data['signature'] = $this->payfast->generateSignature($data); | ||||||
|  |         $data['gateway'] = $this->payfast; | ||||||
|  |         $data['payment_endpoint_url'] = $this->payfast->endpointUrl(); | ||||||
|  | 
 | ||||||
|  |         return render('gateways.payfast.authorize', $data); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |       'm_payment_id' => NULL, | ||||||
|  |       'pf_payment_id' => '1409993', | ||||||
|  |       'payment_status' => 'COMPLETE',  | ||||||
|  |       'item_name' => 'pre-auth', | ||||||
|  |       'item_description' => NULL, | ||||||
|  |       'amount_gross' => '5.00', | ||||||
|  |       'amount_fee' => '-2.53', | ||||||
|  |       'amount_net' => '2.47', | ||||||
|  |       'custom_str1' => NULL, | ||||||
|  |       'custom_str2' => NULL, | ||||||
|  |       'custom_str3' => NULL, | ||||||
|  |       'custom_str4' => NULL, | ||||||
|  |       'custom_str5' => NULL, | ||||||
|  |       'custom_int1' => NULL, | ||||||
|  |       'custom_int2' => NULL, | ||||||
|  |       'custom_int3' => NULL, | ||||||
|  |       'custom_int4' => NULL, | ||||||
|  |       'custom_int5' => NULL, | ||||||
|  |       'name_first' => NULL, | ||||||
|  |       'name_last' => NULL, | ||||||
|  |       'email_address' => NULL, | ||||||
|  |       'merchant_id' => '10023100', | ||||||
|  |       'token' => '34b66bc2-3c54-9590-03ea-42ee8b89922a', | ||||||
|  |       'billing_date' => '2021-07-05', | ||||||
|  |       'signature' => 'ebdb4ca937d0e3f43462841c0afc6ad9', | ||||||
|  |       'q' => '/payment_notification_webhook/EhbnVYyzJZyccY85hcHIkIzNPI2rtHzznAyyyG73oSxZidAdN9gf8BvAKDomqeHp/4openRe7Az/WPe99p3eLy', | ||||||
|  |      */ | ||||||
|  |  	public function authorizeResponse($request) | ||||||
|  |  	{ | ||||||
|  |         $data = $request->all(); | ||||||
|  | 
 | ||||||
|  |         $cgt = []; | ||||||
|  |         $cgt['token'] = $data['token']; | ||||||
|  |         $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; | ||||||
|  | 
 | ||||||
|  |         $payment_meta = new \stdClass; | ||||||
|  |         $payment_meta->exp_month = 'xx'; | ||||||
|  |         $payment_meta->exp_year = 'xx'; | ||||||
|  |         $payment_meta->brand = 'CC'; | ||||||
|  |         $payment_meta->last4 = 'xxxx'; | ||||||
|  |         $payment_meta->type = GatewayType::CREDIT_CARD; | ||||||
|  | 
 | ||||||
|  |         $cgt['payment_meta'] = $payment_meta; | ||||||
|  | 
 | ||||||
|  |         $token = $this->payfast->storeGatewayToken($cgt, []); | ||||||
|  | 
 | ||||||
|  |         return response()->json([], 200); | ||||||
|  | 
 | ||||||
|  |  	}   | ||||||
|  | 
 | ||||||
|  |     public function paymentView($data) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $payfast_data = [ | ||||||
|  |             'merchant_id' => $this->payfast->company_gateway->getConfigField('merchantId'), | ||||||
|  |             'merchant_key' => $this->payfast->company_gateway->getConfigField('merchantKey'), | ||||||
|  |             'return_url' => route('client.payments.index'), | ||||||
|  |             'cancel_url' => route('client.payment_methods.index'), | ||||||
|  |             'notify_url' => $this->payfast->genericWebhookUrl(), | ||||||
|  |             'm_payment_id' => $data['payment_hash'], | ||||||
|  |             'amount' => $data['amount_with_fee'], | ||||||
|  |             'item_name' => 'purchase', | ||||||
|  |             'item_description' => ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number'), | ||||||
|  |             'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'), | ||||||
|  |         ];   | ||||||
|  | 
 | ||||||
|  |         $payfast_data['signature'] = $this->payfast->generateSignature($payfast_data); | ||||||
|  |         $payfast_data['gateway'] = $this->payfast; | ||||||
|  |         $payfast_data['payment_endpoint_url'] = $this->payfast->endpointUrl(); | ||||||
|  | 
 | ||||||
|  |         return render('gateways.payfast.pay', array_merge($data, $payfast_data)); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |     [2021-07-05 11:21:24] local.INFO: array ( | ||||||
|  |       'm_payment_id' => 'B7G9Q2vPhqkLEoMwwY1paXvPGuFxpbDe', | ||||||
|  |       'pf_payment_id' => '1410364', | ||||||
|  |       'payment_status' => 'COMPLETE', | ||||||
|  |       'item_name' => 'purchase', | ||||||
|  |       'item_description' => 'Invoices: ["0001"]', | ||||||
|  |       'amount_gross' => '100.00', | ||||||
|  |       'amount_fee' => '-2.30', | ||||||
|  |       'amount_net' => '97.70', | ||||||
|  |       'custom_str1' => NULL, | ||||||
|  |       'custom_str2' => NULL, | ||||||
|  |       'custom_str3' => NULL, | ||||||
|  |       'custom_str4' => NULL, | ||||||
|  |       'custom_str5' => NULL, | ||||||
|  |       'custom_int1' => NULL, | ||||||
|  |       'custom_int2' => NULL, | ||||||
|  |       'custom_int3' => NULL, | ||||||
|  |       'custom_int4' => NULL, | ||||||
|  |       'custom_int5' => NULL, | ||||||
|  |       'name_first' => NULL, | ||||||
|  |       'name_last' => NULL, | ||||||
|  |       'email_address' => NULL, | ||||||
|  |       'merchant_id' => '10023100', | ||||||
|  |       'signature' => '3ed27638479fd65cdffb0f4910679d10', | ||||||
|  |       'q' => '/payment_notification_webhook/EhbnVYyzJZyccY85hcHIkIzNPI2rtHzznAyyyG73oSxZidAdN9gf8BvAKDomqeHp/4openRe7Az/WPe99p3eLy', | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |      */ | ||||||
|  |     public function paymentResponse(Request $request) | ||||||
|  |     { | ||||||
|  |         $response_array = $request->all(); | ||||||
|  | 
 | ||||||
|  |         $state = [ | ||||||
|  |             'server_response' => $request->all(), | ||||||
|  |             'payment_hash' => $request->input('m_payment_id'), | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         $this->payfast->payment_hash->data = array_merge((array) $this->payfast->payment_hash->data, $state); | ||||||
|  |         $this->payfast->payment_hash->save(); | ||||||
|  | 
 | ||||||
|  |         if($response_array['payment_status'] == 'COMPLETE') { | ||||||
|  | 
 | ||||||
|  |             $this->payfast->logSuccessfulGatewayResponse(['response' => $response_array, 'data' => $this->payfast->payment_hash], SystemLog::TYPE_PAYFAST); | ||||||
|  | 
 | ||||||
|  |             return $this->processSuccessfulPayment($response_array); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             $this->processUnsuccessfulPayment($response_array); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private function processSuccessfulPayment($response_array) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $payment_record = []; | ||||||
|  |         $payment_record['amount'] = $response_array['amount_gross']; | ||||||
|  |         $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER; | ||||||
|  |         $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD; | ||||||
|  |         $payment_record['transaction_reference'] = $response_array['pf_payment_id']; | ||||||
|  | 
 | ||||||
|  |         $payment = $this->payfast->createPayment($payment_record, Payment::STATUS_COMPLETED); | ||||||
|  | 
 | ||||||
|  |         return redirect()->route('client.payments.show', ['payment' => $this->payfast->encodePrimaryKey($payment->id)]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private function processUnsuccessfulPayment($server_response) | ||||||
|  |     { | ||||||
|  |         PaymentFailureMailer::dispatch($this->payfast->client, $server_response->cancellation_reason, $this->payfast->client->company, $server_response->amount); | ||||||
|  | 
 | ||||||
|  |         PaymentFailureMailer::dispatch( | ||||||
|  |             $this->payfast->client, | ||||||
|  |             $server_response, | ||||||
|  |             $this->payfast->client->company, | ||||||
|  |             $server_response['amount_gross'] | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         $message = [ | ||||||
|  |             'server_response' => $server_response, | ||||||
|  |             'data' => $this->payfast->payment_hash->data, | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         SystemLogger::dispatch( | ||||||
|  |             $message, | ||||||
|  |             SystemLog::CATEGORY_GATEWAY_RESPONSE, | ||||||
|  |             SystemLog::EVENT_GATEWAY_FAILURE, | ||||||
|  |             SystemLog::TYPE_PAYFAST, | ||||||
|  |             $this->payfast->client, | ||||||
|  |             $this->payfast->client->company, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         throw new PaymentFailed('Failed to process the payment.', 500); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										184
									
								
								app/PaymentDrivers/PayFast/Token.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								app/PaymentDrivers/PayFast/Token.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,184 @@ | |||||||
|  | <?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\PayFast; | ||||||
|  | 
 | ||||||
|  | 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\Payment; | ||||||
|  | use App\Models\PaymentHash; | ||||||
|  | use App\Models\PaymentType; | ||||||
|  | use App\Models\SystemLog; | ||||||
|  | use App\PaymentDrivers\PayFastPaymentDriver; | ||||||
|  | use Illuminate\Http\Request; | ||||||
|  | use Illuminate\Support\Facades\Cache; | ||||||
|  | use Illuminate\Support\Str; | ||||||
|  | use GuzzleHttp\RequestOptions; | ||||||
|  | 
 | ||||||
|  | class Token | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public $payfast; | ||||||
|  | 
 | ||||||
|  |     //https://api.payfast.co.za/subscriptions/dc0521d3-55fe-269b-fa00-b647310d760f/adhoc 
 | ||||||
|  | 
 | ||||||
|  |     public function __construct(PayFastPaymentDriver $payfast) | ||||||
|  |     { | ||||||
|  |         $this->payfast = $payfast; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	// Attributes
 | ||||||
|  | 	// merchant-id
 | ||||||
|  | 	// integer, 8 char | REQUIRED
 | ||||||
|  | 	// Header, the Merchant ID as given by the PayFast system.
 | ||||||
|  | 	// version
 | ||||||
|  | 	// string | REQUIRED
 | ||||||
|  | 	// Header, the PayFast API version (i.e. v1).
 | ||||||
|  | 	// timestamp
 | ||||||
|  | 	// ISO-8601 date and time | REQUIRED
 | ||||||
|  | 	// Header, the current timestamp (YYYY-MM-DDTHH:MM:SS[+HH:MM]).
 | ||||||
|  | 	// signature
 | ||||||
|  | 	// string | REQUIRED
 | ||||||
|  | 	// Header, MD5 hash of the alphabetised submitted header and body variables, as well as the passphrase. Characters must be in lower case.
 | ||||||
|  | 	// amount
 | ||||||
|  | 	// integer | REQUIRED
 | ||||||
|  | 	// Body, the amount which the buyer must pay, in cents (ZAR), no decimals.
 | ||||||
|  | 	// item_name
 | ||||||
|  | 	// string, 100 char | REQUIRED
 | ||||||
|  | 	// Body, the name of the item being charged for.
 | ||||||
|  | 	// item_description
 | ||||||
|  | 	// string, 255 char | OPTIONAL
 | ||||||
|  | 	// Body, the description of the item being charged for.
 | ||||||
|  | 	// itn
 | ||||||
|  | 	// boolean | OPTIONAL
 | ||||||
|  | 	// Body, specify whether an ITN must be sent for the tokenization payment (true by default).
 | ||||||
|  | 	// m_payment_id
 | ||||||
|  | 	// string, 100 char | OPTIONAL
 | ||||||
|  | 	// Body, unique payment ID on the merchant’s system.
 | ||||||
|  | 	// cc_cvv
 | ||||||
|  | 	// numeric | OPTIONAL
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total; | ||||||
|  | 		$amount = round(($amount * pow(10, $this->payfast->client->currency()->precision)),0); | ||||||
|  | 
 | ||||||
|  | 		$header =[ | ||||||
|  |             'merchant-id' => $this->payfast->company_gateway->getConfigField('merchantId'), | ||||||
|  |             'timestamp' => now()->format('c'), | ||||||
|  |             'version' => 'v1', | ||||||
|  | 		]; | ||||||
|  | 
 | ||||||
|  |         nlog($header); | ||||||
|  | 
 | ||||||
|  |         $body = [ | ||||||
|  |             'amount' => $amount, | ||||||
|  |             'item_name' => 'purchase', | ||||||
|  |             'item_description' => ctrans('texts.invoices') . ': ' . collect($payment_hash->invoices())->pluck('invoice_number'), | ||||||
|  |             'm_payment_id' => $payment_hash->hash, | ||||||
|  |             'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'), | ||||||
|  |         ];         | ||||||
|  | 
 | ||||||
|  |         $header['signature'] = $this->genSig(array_merge($header, $body)); | ||||||
|  | 
 | ||||||
|  |         nlog($header['signature']); | ||||||
|  |         nlog($header['timestamp']); | ||||||
|  |         nlog($this->payfast->company_gateway->getConfigField('merchantId')); | ||||||
|  |          | ||||||
|  |         $result = $this->send($header, $body, $cgt->token); | ||||||
|  | 
 | ||||||
|  |         nlog($result); | ||||||
|  |          | ||||||
|  |         // /*Refactor and push to BaseDriver*/
 | ||||||
|  |         // if ($data['response'] != null && $data['response']->getMessages()->getResultCode() == 'Ok') {
 | ||||||
|  | 
 | ||||||
|  |         //     $response = $data['response'];
 | ||||||
|  | 
 | ||||||
|  |         //     $this->storePayment($payment_hash, $data);
 | ||||||
|  | 
 | ||||||
|  |         //     $vars = [
 | ||||||
|  |         //         'invoices' => $payment_hash->invoices(),
 | ||||||
|  |         //         'amount' => $amount,
 | ||||||
|  |         //     ];
 | ||||||
|  | 
 | ||||||
|  |         //     $logger_message = [
 | ||||||
|  |         //         'server_response' => $response->getTransactionResponse()->getTransId(),
 | ||||||
|  |         //         'data' => $this->formatGatewayResponse($data, $vars),
 | ||||||
|  |         //     ];
 | ||||||
|  | 
 | ||||||
|  |         //     SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_AUTHORIZE, $this->authorize->client, $this->authorize->client->company);
 | ||||||
|  | 
 | ||||||
|  |         //     return true;
 | ||||||
|  |         // } else {
 | ||||||
|  | 
 | ||||||
|  |         //     $vars = [
 | ||||||
|  |         //         'invoices' => $payment_hash->invoices(),
 | ||||||
|  |         //         'amount' => $amount,
 | ||||||
|  |         //     ];
 | ||||||
|  | 
 | ||||||
|  |         //     $logger_message = [
 | ||||||
|  |         //         'server_response' => $response->getTransactionResponse()->getTransId(),
 | ||||||
|  |         //         'data' => $this->formatGatewayResponse($data, $vars),
 | ||||||
|  |         //     ];
 | ||||||
|  | 
 | ||||||
|  |         //     PaymentFailureMailer::dispatch($this->authorize->client, $response->getTransactionResponse()->getTransId(), $this->authorize->client->company, $amount);
 | ||||||
|  | 
 | ||||||
|  |         //     SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_AUTHORIZE, $this->authorize->client, $this->authorize->client->company);
 | ||||||
|  | 
 | ||||||
|  |         //     return false;
 | ||||||
|  |         // }
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private function genSig($data) | ||||||
|  |     { | ||||||
|  |     	$fields = []; | ||||||
|  | 
 | ||||||
|  |     	ksort($data); | ||||||
|  | 
 | ||||||
|  |         foreach($data as $key => $value) | ||||||
|  |         { | ||||||
|  |         	if (!empty($data[$key])) { | ||||||
|  |                 $fields[$key] = $data[$key]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return md5(http_build_query($fields)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private function send($headers, $body, $token) | ||||||
|  |     { | ||||||
|  |     	$client =  new \GuzzleHttp\Client( | ||||||
|  |         [ | ||||||
|  |             'headers' => $headers, | ||||||
|  |         ]); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             $response = $client->post("https://api.payfast.co.za/subscriptions/{$token}/adhoc?testing=true",[ | ||||||
|  |                 RequestOptions::JSON => ['body' => $body], RequestOptions::ALLOW_REDIRECTS => false | ||||||
|  |             ]); | ||||||
|  | 
 | ||||||
|  |             return json_decode($response->getBody(),true); | ||||||
|  |         } | ||||||
|  |         catch(\Exception $e) | ||||||
|  |         { | ||||||
|  | 
 | ||||||
|  |         	nlog($e->getMessage()); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										202
									
								
								app/PaymentDrivers/PayFastPaymentDriver.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								app/PaymentDrivers/PayFastPaymentDriver.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,202 @@ | |||||||
|  | <?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\Models\ClientGatewayToken; | ||||||
|  | use App\Models\GatewayType; | ||||||
|  | use App\Models\Payment; | ||||||
|  | use App\Models\PaymentHash; | ||||||
|  | use App\Models\SystemLog; | ||||||
|  | use App\PaymentDrivers\PayFast\CreditCard; | ||||||
|  | use App\PaymentDrivers\PayFast\Token; | ||||||
|  | use App\Utils\Traits\MakesHash; | ||||||
|  | use Illuminate\Http\Request; | ||||||
|  | use Illuminate\Support\Facades\Cache; | ||||||
|  | 
 | ||||||
|  | class PayFastPaymentDriver extends BaseDriver | ||||||
|  | { | ||||||
|  |     use MakesHash; | ||||||
|  | 
 | ||||||
|  |     public $refundable = false; //does this gateway support refunds?
 | ||||||
|  | 
 | ||||||
|  |     public $token_billing = false; //does this gateway support token billing?
 | ||||||
|  | 
 | ||||||
|  |     public $can_authorise_credit_card = true; //does this gateway support authorizations?
 | ||||||
|  | 
 | ||||||
|  |     public $payfast; //initialized gateway
 | ||||||
|  | 
 | ||||||
|  |     public $payment_method; //initialized payment method
 | ||||||
|  | 
 | ||||||
|  |     public static $methods = [ | ||||||
|  |         GatewayType::CREDIT_CARD => CreditCard::class, | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|  |     const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYFAST; | ||||||
|  | 
 | ||||||
|  |     //developer resources
 | ||||||
|  |     //https://sandbox.payfast.co.za/
 | ||||||
|  | 
 | ||||||
|  |     public function gatewayTypes(): array | ||||||
|  |     { | ||||||
|  |         $types = []; | ||||||
|  | 
 | ||||||
|  |         if($this->client->currency()->code == 'ZAR') | ||||||
|  |             $types[] = GatewayType::CREDIT_CARD; | ||||||
|  | 
 | ||||||
|  |         return $types; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function endpointUrl() | ||||||
|  |     { | ||||||
|  |         if($this->company_gateway->getConfigField('testMode')) | ||||||
|  |             return 'https://sandbox.payfast.co.za/eng/process'; | ||||||
|  | 
 | ||||||
|  |         return 'https://www.payfast.co.za/eng/process'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function init() | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         try{ | ||||||
|  | 
 | ||||||
|  |             $this->payfast = new \PayFast\PayFastPayment( | ||||||
|  |                 [ | ||||||
|  |                     'merchantId' => $this->company_gateway->getConfigField('merchantId'), | ||||||
|  |                     'merchantKey' => $this->company_gateway->getConfigField('merchantKey'), | ||||||
|  |                     'passPhrase' => $this->company_gateway->getConfigField('passPhrase'), | ||||||
|  |                     'testMode' => $this->company_gateway->getConfigField('testMode') | ||||||
|  |                 ] | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |         } catch(Exception $e) { | ||||||
|  | 
 | ||||||
|  |             echo '##PAYFAST## There was an exception: '.$e->getMessage(); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function authorizeResponse($request) | ||||||
|  |     { | ||||||
|  |         return $this->payment_method->authorizeResponse($request); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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) | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) | ||||||
|  |     { | ||||||
|  |         return (new Token($this))->tokenBilling($cgt, $payment_hash); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |    public function generateSignature($data) | ||||||
|  |     { | ||||||
|  |         $fields = array(); | ||||||
|  | 
 | ||||||
|  |         // specific order required by PayFast
 | ||||||
|  |         // @see https://developers.payfast.co.za/documentation/#checkout-page
 | ||||||
|  |         foreach (array('merchant_id', 'merchant_key', 'return_url', 'cancel_url', 'notify_url', 'name_first', | ||||||
|  |                      'name_last', 'email_address', 'cell_number', | ||||||
|  |                     /** | ||||||
|  |                      * Transaction Details | ||||||
|  |                      */ | ||||||
|  |                     'm_payment_id', 'amount', 'item_name', 'item_description', | ||||||
|  |                     /** | ||||||
|  |                      * Custom return data | ||||||
|  |                      */ | ||||||
|  |                     'custom_int1', 'custom_int2', 'custom_int3', 'custom_int4', 'custom_int5', | ||||||
|  |                     'custom_str1', 'custom_str2', 'custom_str3', 'custom_str4', 'custom_str5', | ||||||
|  |                     /** | ||||||
|  |                      * Email confirmation | ||||||
|  |                      */ | ||||||
|  |                     'email_confirmation', 'confirmation_address', | ||||||
|  |                     /** | ||||||
|  |                      * Payment Method | ||||||
|  |                      */ | ||||||
|  |                     'payment_method', | ||||||
|  |                     /** | ||||||
|  |                      * Subscriptions | ||||||
|  |                      */ | ||||||
|  |                     'subscription_type', 'billing_date', 'recurring_amount', 'frequency', 'cycles', | ||||||
|  |                     /** | ||||||
|  |                      * Passphrase for md5 signature generation | ||||||
|  |                      */ | ||||||
|  |                     'passphrase') as $key) { | ||||||
|  |             if (!empty($data[$key])) { | ||||||
|  |                 $fields[$key] = $data[$key]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return md5(http_build_query($fields)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public function processWebhookRequest(Request $request, Payment $payment = null) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $data = $request->all(); | ||||||
|  |         nlog($data); | ||||||
|  | 
 | ||||||
|  |         if(array_key_exists('m_payment_id', $data)) | ||||||
|  |         { | ||||||
|  | 
 | ||||||
|  |             $hash = Cache::get($data['m_payment_id']); | ||||||
|  | 
 | ||||||
|  |             switch ($hash) | ||||||
|  |             { | ||||||
|  |                 case 'cc_auth': | ||||||
|  |                     return $this->setPaymentMethod(GatewayType::CREDIT_CARD) | ||||||
|  |                                 ->authorizeResponse($request); | ||||||
|  |                     break; | ||||||
|  | 
 | ||||||
|  |                 default: | ||||||
|  | 
 | ||||||
|  |                     $payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$data['m_payment_id']])->first(); | ||||||
|  | 
 | ||||||
|  |                     return $this->setPaymentMethod(GatewayType::CREDIT_CARD) | ||||||
|  |                                 ->setPaymentHash($payment_hash) | ||||||
|  |                                 ->processPaymentResponse($request); | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return response()->json([], 200); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -117,7 +117,6 @@ use WePayCommon; | |||||||
|             nlog("authorize the card first!"); |             nlog("authorize the card first!"); | ||||||
| 
 | 
 | ||||||
|             $response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array( |             $response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array( | ||||||
|                 // 'callback_uri'        => route('payment_webhook', ['company_key' => $this->wepay_payment_driver->company_gateway->company->company_key, 'company_gateway_id' => $this->wepay_payment_driver->company_gateway->hashed_id]),
 |  | ||||||
|                 'client_id'          => config('ninja.wepay.client_id'), |                 'client_id'          => config('ninja.wepay.client_id'), | ||||||
|                 'client_secret'      => config('ninja.wepay.client_secret'), |                 'client_secret'      => config('ninja.wepay.client_secret'), | ||||||
|                 'credit_card_id'     => (int)$request->input('credit_card_id'), |                 'credit_card_id'     => (int)$request->input('credit_card_id'), | ||||||
|  | |||||||
| @ -71,6 +71,7 @@ class HandleReversal extends AbstractService | |||||||
|             $credit = CreditFactory::create($this->invoice->company_id, $this->invoice->user_id); |             $credit = CreditFactory::create($this->invoice->company_id, $this->invoice->user_id); | ||||||
|             $credit->client_id = $this->invoice->client_id; |             $credit->client_id = $this->invoice->client_id; | ||||||
|             $credit->invoice_id = $this->invoice->id; |             $credit->invoice_id = $this->invoice->id; | ||||||
|  |             $credit->date = now(); | ||||||
|              |              | ||||||
|             $item = InvoiceItemFactory::create(); |             $item = InvoiceItemFactory::create(); | ||||||
|             $item->quantity = 1; |             $item->quantity = 1; | ||||||
|  | |||||||
| @ -77,6 +77,7 @@ class SubscriptionService | |||||||
|             $recurring_invoice->next_send_date = now(); |             $recurring_invoice->next_send_date = now(); | ||||||
|             $recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice); |             $recurring_invoice = $recurring_invoice_repo->save([], $recurring_invoice); | ||||||
|             $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); |             $recurring_invoice->next_send_date = $recurring_invoice->nextSendDate(); | ||||||
|  |             $recurring_invoice->auto_bill = $this->subscription->auto_bill; | ||||||
|              |              | ||||||
|             /* Start the recurring service */ |             /* Start the recurring service */ | ||||||
|             $recurring_invoice->service() |             $recurring_invoice->service() | ||||||
|  | |||||||
| @ -26,9 +26,9 @@ use App\Utils\CurlUtils; | |||||||
| use App\Utils\HtmlEngine; | use App\Utils\HtmlEngine; | ||||||
| use App\Utils\Traits\MakesHash; | use App\Utils\Traits\MakesHash; | ||||||
| use Illuminate\Support\Facades\App; | use Illuminate\Support\Facades\App; | ||||||
| use Illuminate\Support\Facades\Cache; |  | ||||||
| use Illuminate\Support\Facades\Response; | use Illuminate\Support\Facades\Response; | ||||||
| use Illuminate\Support\Facades\Storage; | use Illuminate\Support\Facades\Storage; | ||||||
|  | use Illuminate\Support\Facades\Cache; | ||||||
| use Illuminate\Support\Str; | use Illuminate\Support\Str; | ||||||
| 
 | 
 | ||||||
| class Phantom | class Phantom | ||||||
|  | |||||||
| @ -64,6 +64,7 @@ | |||||||
|         "maennchen/zipstream-php": "^1.2", |         "maennchen/zipstream-php": "^1.2", | ||||||
|         "nwidart/laravel-modules": "^8.0", |         "nwidart/laravel-modules": "^8.0", | ||||||
|         "omnipay/paypal": "^3.0", |         "omnipay/paypal": "^3.0", | ||||||
|  |         "payfast/payfast-php-sdk": "^1.1", | ||||||
|         "pragmarx/google2fa": "^8.0", |         "pragmarx/google2fa": "^8.0", | ||||||
|         "predis/predis": "^1.1", |         "predis/predis": "^1.1", | ||||||
|         "sentry/sentry-laravel": "^2", |         "sentry/sentry-laravel": "^2", | ||||||
|  | |||||||
							
								
								
									
										101
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										101
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							| @ -4,7 +4,7 @@ | |||||||
|         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", |         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||||
|         "This file is @generated automatically" |         "This file is @generated automatically" | ||||||
|     ], |     ], | ||||||
|     "content-hash": "16a38ffa3774d9d28a9f4c49366baac0", |     "content-hash": "25a0cbf18fc238305c7ea640c49ba89a", | ||||||
|     "packages": [ |     "packages": [ | ||||||
|         { |         { | ||||||
|             "name": "asm/php-ansible", |             "name": "asm/php-ansible", | ||||||
| @ -159,16 +159,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "aws/aws-sdk-php", |             "name": "aws/aws-sdk-php", | ||||||
|             "version": "3.185.7", |             "version": "3.185.10", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/aws/aws-sdk-php.git", |                 "url": "https://github.com/aws/aws-sdk-php.git", | ||||||
|                 "reference": "7c0cd260e749374b5df247c4768c8f33f9a604e4" |                 "reference": "667a83e4a18cb75db3ce74162efc97123da96261" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7c0cd260e749374b5df247c4768c8f33f9a604e4", |                 "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/667a83e4a18cb75db3ce74162efc97123da96261", | ||||||
|                 "reference": "7c0cd260e749374b5df247c4768c8f33f9a604e4", |                 "reference": "667a83e4a18cb75db3ce74162efc97123da96261", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @ -243,9 +243,9 @@ | |||||||
|             "support": { |             "support": { | ||||||
|                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", |                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", | ||||||
|                 "issues": "https://github.com/aws/aws-sdk-php/issues", |                 "issues": "https://github.com/aws/aws-sdk-php/issues", | ||||||
|                 "source": "https://github.com/aws/aws-sdk-php/tree/3.185.7" |                 "source": "https://github.com/aws/aws-sdk-php/tree/3.185.10" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-07-06T18:16:14+00:00" |             "time": "2021-07-09T19:21:22+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "bacon/bacon-qr-code", |             "name": "bacon/bacon-qr-code", | ||||||
| @ -4113,16 +4113,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/oauth1-client", |             "name": "league/oauth1-client", | ||||||
|             "version": "v1.9.0", |             "version": "v1.9.1", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/thephpleague/oauth1-client.git", |                 "url": "https://github.com/thephpleague/oauth1-client.git", | ||||||
|                 "reference": "1e7e6be2dc543bf466236fb171e5b20e1b06aee6" |                 "reference": "19a3ce488bb1547c906209e8293199ec34eaa5b1" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/1e7e6be2dc543bf466236fb171e5b20e1b06aee6", |                 "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/19a3ce488bb1547c906209e8293199ec34eaa5b1", | ||||||
|                 "reference": "1e7e6be2dc543bf466236fb171e5b20e1b06aee6", |                 "reference": "19a3ce488bb1547c906209e8293199ec34eaa5b1", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @ -4182,9 +4182,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/thephpleague/oauth1-client/issues", |                 "issues": "https://github.com/thephpleague/oauth1-client/issues", | ||||||
|                 "source": "https://github.com/thephpleague/oauth1-client/tree/v1.9.0" |                 "source": "https://github.com/thephpleague/oauth1-client/tree/v1.9.1" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-01-20T01:40:53+00:00" |             "time": "2021-07-07T22:54:46+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/omnipay", |             "name": "league/omnipay", | ||||||
| @ -4251,16 +4251,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "livewire/livewire", |             "name": "livewire/livewire", | ||||||
|             "version": "v2.5.1", |             "version": "v2.5.3", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/livewire/livewire.git", |                 "url": "https://github.com/livewire/livewire.git", | ||||||
|                 "reference": "a4ffb135693e7982e5b982ca203f5dc7a7ae1126" |                 "reference": "1ca6757c78dbead4db7f52a72dabb8b27efcb3f6" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/livewire/livewire/zipball/a4ffb135693e7982e5b982ca203f5dc7a7ae1126", |                 "url": "https://api.github.com/repos/livewire/livewire/zipball/1ca6757c78dbead4db7f52a72dabb8b27efcb3f6", | ||||||
|                 "reference": "a4ffb135693e7982e5b982ca203f5dc7a7ae1126", |                 "reference": "1ca6757c78dbead4db7f52a72dabb8b27efcb3f6", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @ -4311,7 +4311,7 @@ | |||||||
|             "description": "A front-end framework for Laravel.", |             "description": "A front-end framework for Laravel.", | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/livewire/livewire/issues", |                 "issues": "https://github.com/livewire/livewire/issues", | ||||||
|                 "source": "https://github.com/livewire/livewire/tree/v2.5.1" |                 "source": "https://github.com/livewire/livewire/tree/v2.5.3" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @ -4319,7 +4319,7 @@ | |||||||
|                     "type": "github" |                     "type": "github" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2021-06-15T13:24:48+00:00" |             "time": "2021-07-08T13:58:45+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "maennchen/zipstream-php", |             "name": "maennchen/zipstream-php", | ||||||
| @ -5334,6 +5334,57 @@ | |||||||
|             }, |             }, | ||||||
|             "time": "2020-10-15T08:29:30+00:00" |             "time": "2020-10-15T08:29:30+00:00" | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             "name": "payfast/payfast-php-sdk", | ||||||
|  |             "version": "v1.1.2", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/PayFast/payfast-php-sdk.git", | ||||||
|  |                 "reference": "1372980e38f381b84eed7eb46a40d5819a4fe58c" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/PayFast/payfast-php-sdk/zipball/1372980e38f381b84eed7eb46a40d5819a4fe58c", | ||||||
|  |                 "reference": "1372980e38f381b84eed7eb46a40d5819a4fe58c", | ||||||
|  |                 "shasum": "" | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "ext-json": "*", | ||||||
|  |                 "guzzlehttp/guzzle": ">=6.0.0", | ||||||
|  |                 "php": ">=7.2.5" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "phpunit/phpunit": "^9" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-4": { | ||||||
|  |                     "PayFast\\": "lib/" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "MIT" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Claire Grant", | ||||||
|  |                     "email": "claire.grant@payfast.co.za" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "PayFast PHP Library", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "api", | ||||||
|  |                 "onsite", | ||||||
|  |                 "payfast", | ||||||
|  |                 "php" | ||||||
|  |             ], | ||||||
|  |             "support": { | ||||||
|  |                 "issues": "https://github.com/PayFast/payfast-php-sdk/issues", | ||||||
|  |                 "source": "https://github.com/PayFast/payfast-php-sdk/tree/v1.1.2" | ||||||
|  |             }, | ||||||
|  |             "time": "2021-03-15T19:58:26+00:00" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             "name": "php-http/client-common", |             "name": "php-http/client-common", | ||||||
|             "version": "2.4.0", |             "version": "2.4.0", | ||||||
| @ -7319,16 +7370,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "stripe/stripe-php", |             "name": "stripe/stripe-php", | ||||||
|             "version": "v7.87.0", |             "version": "v7.88.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/stripe/stripe-php.git", |                 "url": "https://github.com/stripe/stripe-php.git", | ||||||
|                 "reference": "9392f03cb8d8803bf8273378ce42d5cbbf1e24fc" |                 "reference": "7203d00ba9b09830c0c5d5c06a9558db43b8e0ea" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/stripe/stripe-php/zipball/9392f03cb8d8803bf8273378ce42d5cbbf1e24fc", |                 "url": "https://api.github.com/repos/stripe/stripe-php/zipball/7203d00ba9b09830c0c5d5c06a9558db43b8e0ea", | ||||||
|                 "reference": "9392f03cb8d8803bf8273378ce42d5cbbf1e24fc", |                 "reference": "7203d00ba9b09830c0c5d5c06a9558db43b8e0ea", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @ -7374,9 +7425,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/stripe/stripe-php/issues", |                 "issues": "https://github.com/stripe/stripe-php/issues", | ||||||
|                 "source": "https://github.com/stripe/stripe-php/tree/v7.87.0" |                 "source": "https://github.com/stripe/stripe-php/tree/v7.88.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-06-30T18:22:47+00:00" |             "time": "2021-07-09T20:01:03+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "swiftmailer/swiftmailer", |             "name": "swiftmailer/swiftmailer", | ||||||
|  | |||||||
| @ -109,7 +109,6 @@ return [ | |||||||
|         'gelf' => [ |         'gelf' => [ | ||||||
|             'driver' => 'custom', |             'driver' => 'custom', | ||||||
|              |              | ||||||
| 
 |  | ||||||
|             'via' => \Hedii\LaravelGelfLogger\GelfLoggerFactory::class, |             'via' => \Hedii\LaravelGelfLogger\GelfLoggerFactory::class, | ||||||
| 
 | 
 | ||||||
|             // This optional option determines the processors that should be
 |             // This optional option determines the processors that should be
 | ||||||
|  | |||||||
| @ -0,0 +1,29 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | use App\Models\Gateway; | ||||||
|  | use Illuminate\Database\Migrations\Migration; | ||||||
|  | use Illuminate\Database\Schema\Blueprint; | ||||||
|  | use Illuminate\Support\Facades\Schema; | ||||||
|  | 
 | ||||||
|  | class ActivatePayfastPaymentDriver extends Migration | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Run the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function up() | ||||||
|  |     { | ||||||
|  |         Gateway::whereIn('id', [11])->update(['visible' => 1]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Reverse the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function down() | ||||||
|  |     { | ||||||
|  |         //
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | @extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) | ||||||
|  | 
 | ||||||
|  | @section('gateway_head') | ||||||
|  |     <meta name="contact-email" content="{{ $contact->email }}"> | ||||||
|  |     <meta name="client-postal-code" content="{{ $contact->client->postal_code }}"> | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_content') | ||||||
|  |     <form action="{{ $payment_endpoint_url }}" method="post" id="server_response"> | ||||||
|  |         <input type="hidden" name="merchant_id" value="{{ $merchant_id }}"> | ||||||
|  |         <input type="hidden" name="merchant_key" value="{{ $merchant_key }}"> | ||||||
|  |         <input type="hidden" name="return_url" value="{{ $return_url }}"> | ||||||
|  |         <input type="hidden" name="cancel_url" value="{{ $cancel_url }}"> | ||||||
|  |         <input type="hidden" name="notify_url" value="{{ $notify_url }}"> | ||||||
|  |         <input type="hidden" name="m_payment_id" value="{{ $m_payment_id }}"> | ||||||
|  |         <input type="hidden" name="amount" value="{{ $amount }}"> | ||||||
|  |         <input type="hidden" name="item_name" value="{{ $item_name }}"> | ||||||
|  |         <input type="hidden" name="item_description" value="{{ $item_description}}"> | ||||||
|  |         <input type="hidden" name="subscription_type" value="{{ $subscription_type }}">  | ||||||
|  |         <input type="hidden" name="passphrase" value="{{ $passphrase }}">  | ||||||
|  |         <input type="hidden" name="signature" value="{{ $signature }}">     | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |     @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> | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')]) | ||||||
|  |         {{ ctrans('texts.credit_card') }} | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     <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') | ||||||
|  | 
 | ||||||
|  | @endsection | ||||||
| @ -0,0 +1,74 @@ | |||||||
|  | @extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) | ||||||
|  | 
 | ||||||
|  | @section('gateway_head') | ||||||
|  |     <meta name="contact-email" content="{{ $contact->email }}"> | ||||||
|  |     <meta name="client-postal-code" content="{{ $contact->client->postal_code }}"> | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_content') | ||||||
|  |     <form action="{{ $payment_endpoint_url }}" method="post" id="server_response"> | ||||||
|  |         <input type="hidden" name="merchant_id" value="{{ $merchant_id }}"> | ||||||
|  |         <input type="hidden" name="merchant_key" value="{{ $merchant_key }}"> | ||||||
|  |         <input type="hidden" name="return_url" value="{{ $return_url }}"> | ||||||
|  |         <input type="hidden" name="cancel_url" value="{{ $cancel_url }}"> | ||||||
|  |         <input type="hidden" name="notify_url" value="{{ $notify_url }}"> | ||||||
|  |         <input type="hidden" name="m_payment_id" value="{{ $m_payment_id }}"> | ||||||
|  |         <input type="hidden" name="amount" value="{{ $amount }}"> | ||||||
|  |         <input type="hidden" name="item_name" value="{{ $item_name }}"> | ||||||
|  |         <input type="hidden" name="item_description" value="{{ $item_description}}"> | ||||||
|  |         <input type="hidden" name="passphrase" value="{{ $passphrase }}">  | ||||||
|  |         <input type="hidden" name="signature" value="{{ $signature }}">     | ||||||
|  | 
 | ||||||
|  |     <div class="alert alert-failure mb-4" hidden id="errors"></div> | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')]) | ||||||
|  |         {{ 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->token }}" | ||||||
|  |                         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') | ||||||
|  | 
 | ||||||
|  |     @include('portal.ninja2020.gateways.wepay.includes.credit_card') | ||||||
|  | 
 | ||||||
|  |     @include('portal.ninja2020.gateways.includes.pay_now') | ||||||
|  | 
 | ||||||
|  |    </form>  | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_footer') | ||||||
|  | <script> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     document.getElementById('pay-now').addEventListener('click', function() { | ||||||
|  |       document.getElementById('server_response').submit(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
| @ -198,6 +198,10 @@ Route::match(['get', 'post'], 'payment_webhook/{company_key}/{company_gateway_id | |||||||
|     ->middleware(['guest']) |     ->middleware(['guest']) | ||||||
|     ->name('payment_webhook'); |     ->name('payment_webhook'); | ||||||
| 
 | 
 | ||||||
|  | Route::match(['get', 'post'], 'payment_notification_webhook/{company_key}/{company_gateway_id}/{client}', 'PaymentNotificationWebhookController') | ||||||
|  |     ->middleware(['guest']) | ||||||
|  |     ->name('payment_notification_webhook'); | ||||||
|  | 
 | ||||||
| Route::post('api/v1/postmark_webhook', 'PostMarkController@webhook'); | Route::post('api/v1/postmark_webhook', 'PostMarkController@webhook'); | ||||||
| Route::get('token_hash_router', 'OneTimeTokenController@router'); | Route::get('token_hash_router', 'OneTimeTokenController@router'); | ||||||
| Route::get('webcron', 'WebCronController@index'); | Route::get('webcron', 'WebCronController@index'); | ||||||
|  | |||||||
							
								
								
									
										67
									
								
								tests/Unit/CentConversionTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								tests/Unit/CentConversionTest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | <?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://opensource.org/licenses/AAL | ||||||
|  |  */ | ||||||
|  | namespace Tests\Unit; | ||||||
|  | 
 | ||||||
|  | use App\DataMapper\ClientSettings; | ||||||
|  | use Tests\TestCase; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * @test | ||||||
|  |  */ | ||||||
|  | class CentConversionTest extends TestCase | ||||||
|  | { | ||||||
|  |     public function setUp() :void | ||||||
|  |     { | ||||||
|  |         parent::setUp(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testConversionOfDecimalValues() | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $precision = 2; | ||||||
|  | 
 | ||||||
|  |         $amount = 10.20; | ||||||
|  |         $amount = round(($amount * pow(10, $precision)),0); | ||||||
|  | 
 | ||||||
|  |         $this->assertEquals(1020, $amount); | ||||||
|  | 
 | ||||||
|  |         $amount = 2; | ||||||
|  |         $amount = round(($amount * pow(10, $precision)),0); | ||||||
|  | 
 | ||||||
|  |         $this->assertEquals(200, $amount); | ||||||
|  | 
 | ||||||
|  |         $amount = 2.12; | ||||||
|  |         $amount = round(($amount * pow(10, $precision)),0); | ||||||
|  | 
 | ||||||
|  |         $this->assertEquals(212, $amount); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public function testBcMathWay() | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         $amount = 64.99; | ||||||
|  |         $amount = bcmul($amount, 100); | ||||||
|  |          | ||||||
|  |         $this->assertEquals(6499, $amount); | ||||||
|  | 
 | ||||||
|  |         $amount = 2; | ||||||
|  |         $amount = bcmul($amount, 100); | ||||||
|  | 
 | ||||||
|  |         $this->assertEquals(200, $amount); | ||||||
|  | 
 | ||||||
|  |         $amount = 2.12; | ||||||
|  |         $amount = bcmul($amount, 100); | ||||||
|  | 
 | ||||||
|  |         $this->assertEquals(212, $amount); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -16,6 +16,7 @@ use App\Models\Company; | |||||||
| use App\Models\Credit; | use App\Models\Credit; | ||||||
| use App\Models\CreditInvitation; | use App\Models\CreditInvitation; | ||||||
| use App\Models\User; | use App\Models\User; | ||||||
|  | use App\Utils\Traits\AppSetup; | ||||||
| use Tests\MockUnitData; | use Tests\MockUnitData; | ||||||
| use Tests\TestCase; | use Tests\TestCase; | ||||||
| 
 | 
 | ||||||
| @ -25,6 +26,7 @@ use Tests\TestCase; | |||||||
| class CreditBalanceTest extends TestCase | class CreditBalanceTest extends TestCase | ||||||
| { | { | ||||||
|     use MockUnitData; |     use MockUnitData; | ||||||
|  |     use AppSetup; | ||||||
| 
 | 
 | ||||||
|     public function setUp() :void |     public function setUp() :void | ||||||
|     { |     { | ||||||
| @ -35,6 +37,8 @@ class CreditBalanceTest extends TestCase | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         $this->makeTestData(); |         $this->makeTestData(); | ||||||
|  |      | ||||||
|  |         $this->buildCache(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function testCreditBalance() |     public function testCreditBalance() | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user