From 0347ca00f57f03b59349e7a941f1621a663b88f6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 17 May 2021 14:02:43 +1000 Subject: [PATCH] Update payment methods for Stripe --- app/Http/Controllers/StripeController.php | 35 ++++ app/Jobs/Util/StripeUpdatePaymentMethods.php | 68 +++++++ .../Stripe/UpdatePaymentMethods.php | 168 ++++++++++++++++++ app/PaymentDrivers/StripePaymentDriver.php | 26 +++ routes/api.php | 4 +- 5 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/StripeController.php create mode 100644 app/Jobs/Util/StripeUpdatePaymentMethods.php create mode 100644 app/PaymentDrivers/Stripe/UpdatePaymentMethods.php diff --git a/app/Http/Controllers/StripeController.php b/app/Http/Controllers/StripeController.php new file mode 100644 index 000000000000..2a17496b4af9 --- /dev/null +++ b/app/Http/Controllers/StripeController.php @@ -0,0 +1,35 @@ +user()->isAdmin()) + { + + StripeUpdatePaymentMethods::dispatch(auth()->user()->getCompany()); + + return response()->json(['message' => 'Processing'], 403); + + } + + + return response()->json(['message' => 'Unauthorized'], 403); + } + +} \ No newline at end of file diff --git a/app/Jobs/Util/StripeUpdatePaymentMethods.php b/app/Jobs/Util/StripeUpdatePaymentMethods.php new file mode 100644 index 000000000000..e2183daa9a43 --- /dev/null +++ b/app/Jobs/Util/StripeUpdatePaymentMethods.php @@ -0,0 +1,68 @@ +company = $company; + } + + /** + * Execute the job. + * + * @return bool + */ + public function handle() + { + + MultiDB::setDb($this->company->db); + + $cgs = CompanyGateway::where('company_id', $this->company->id) + ->whereIn('gateway_key', $this->stripe_keys) + ->get(); + + $cgs->each(function ($company_gateway){ + + $company_gateway->driver(new Client)->updateAllPaymentMethods(); + + }); + + } + + public function failed($exception) + { + nlog("Stripe update payment methods exception"); + nlog($exception->getMessage()); + } +} diff --git a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php new file mode 100644 index 000000000000..360b5f451441 --- /dev/null +++ b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php @@ -0,0 +1,168 @@ +stripe = $stripe; + } + + public function run() + { + $this->stripe->init(); + + $this->stripe + ->company_gateway + ->client_gateway_tokens + ->each(function ($token){ + + $card_methods = PaymentMethod::all([ + 'customer' => $token->gateway_customer_reference, + 'type' => 'card', + ], + $this->stripe->stripe_connect_auth); + + foreach($card_methods as $method) + { + $this->addOrUpdateCard($method, $token, GatewayType::CREDIT_CARD); + } + + $alipay_methods = PaymentMethod::all([ + 'customer' => $token->gateway_customer_reference, + 'type' => 'alipay', + ], + $this->stripe->stripe_connect_auth); + + foreach($alipay_methods as $method) + { + $this->addOrUpdateCard($method, $token, GatewayType::ALIPAY); + } + + $sofort_methods = PaymentMethod::all([ + 'customer' => $token->gateway_customer_reference, + 'type' => 'sofort', + ], + $this->stripe->stripe_connect_auth); + + foreach($alipay_methods as $method) + { + $this->addOrUpdateCard($method, $token, GatewayType::SOFORT); + } + + $bank_accounts = Customer::allSources( + $token->gateway_customer_reference, + ['object' => 'bank_account', 'limit' => 300] + ); + + foreach($bank_accounts as $bank_account) + { + $this->addOrUpdateBankAccount($bank_account, $token); + } + + }); + + } + + private function addOrUpdateBankAccount($bank_account, ClientGatewayToken $token) + { + $token_exists = ClientGatewayToken::where([ + 'gateway_customer_reference' => $token->gateway_customer_reference, + 'token' => $bank_account->id, + ])->exists(); + + /* Already exists return */ + if($token_exists) + return; + + $cgt = ClientGatewayTokenFactory::create($token->company_id); + $cgt->client_id = $token->client_id; + $cgt->token = $bank_account->id; + $cgt->gateway_customer_reference = $token->gateway_customer_reference; + $cgt->company_gateway_id = $token->company_gateway_id; + $cgt->gateway_type_id = GatewayType::BANK_TRANSFER + $cgt->meta = new \stdClass; + $cgt->routing_number = $bank_account->routing_number; + $cgt->save(); + + } + + private function addOrUpdateCard(PaymentMethod $method, ClientGatewayToken $token, GatewayType $type_id) + { + + $token_exists = ClientGatewayToken::where([ + 'gateway_customer_reference' => $token->gateway_customer_reference, + 'token' => $method->id, + ])->exists(); + + /* Already exists return */ + if($token_exists) + return; + + /* Ignore Expired cards */ + if($method->card->exp_year <= date('Y') && $method->card->exp_month < date('m')) + return; + + $cgt = ClientGatewayTokenFactory::create($token->company_id); + $cgt->client_id = $token->client_id; + $cgt->token = $method->id; + $cgt->gateway_customer_reference = $token->gateway_customer_reference; + $cgt->company_gateway_id = $token->company_gateway_id; + $cgt->gateway_type_id = $type_id; + $cgt->meta = $this->buildPaymentMethodMeta($method, $type_id); + $cgt->save(); + + } + + private function buildPaymentMethodMeta(PaymentMethod $method, GatewayType $type_id) + { + + switch ($type_id) { + case GatewayType::CREDIT_CARD: + + $payment_meta = new \stdClass; + $payment_meta->exp_month = (string) $method->card->exp_month; + $payment_meta->exp_year = (string) $method->card->exp_year; + $payment_meta->brand = (string) $method->card->brand; + $payment_meta->last4 = (string) $method->card->last4; + $payment_meta->type = GatewayType::CREDIT_CARD; + return $payment_meta; + + break; + + case GatewayType::ALIPAY: + case GatewayType::SOFORT: + + return new \stdClass; + + default: + + + break; + } + } +} diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 2fdb5f27e5a3..3f420dd76c8d 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -26,6 +26,7 @@ use App\PaymentDrivers\Stripe\Alipay; use App\PaymentDrivers\Stripe\Charge; use App\PaymentDrivers\Stripe\CreditCard; use App\PaymentDrivers\Stripe\SOFORT; +use App\PaymentDrivers\Stripe\UpdatePaymentMethods; use App\PaymentDrivers\Stripe\Utilities; use App\Utils\Traits\MakesHash; use Exception; @@ -493,4 +494,29 @@ class StripePaymentDriver extends BaseDriver return Account::all(); } + + /** + * Pull all client payment methods and update + * the respective tokens in the system. + * + */ + public function updateAllPaymentMethods() + { + return (new UpdatePaymentMethods($this))->run(); + } + + /** + * Imports stripe customers and their payment methods + * Matches users in the system based on the $match_on_record + * ie. email + * + * Phone + * Email + */ + public function importAndUpdateCustomers() + { + + //match clients based on the gateway_customer_reference column + + } } diff --git a/routes/api.php b/routes/api.php index 74b994c693c3..2979829ead17 100644 --- a/routes/api.php +++ b/routes/api.php @@ -183,6 +183,8 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a // Route::post('hooks', 'SubscriptionController@subscribe')->name('hooks.subscribe'); // Route::delete('hooks/{subscription_id}', 'SubscriptionController@unsubscribe')->name('hooks.unsubscribe'); + Route::post('stripe/update_payment_methods', 'StripeController@update')->middleware('password_protected')->name('stripe.update'); + Route::resource('subscriptions', 'SubscriptionController'); Route::post('subscriptions/bulk', 'SubscriptionController@bulk')->name('subscriptions.bulk'); @@ -193,9 +195,7 @@ Route::match(['get', 'post'], 'payment_webhook/{company_key}/{company_gateway_id ->name('payment_webhook'); Route::post('api/v1/postmark_webhook', 'PostMarkController@webhook'); - Route::get('token_hash_router', 'OneTimeTokenController@router'); - Route::get('webcron', 'WebCronController@index'); Route::fallback('BaseController@notFound');