Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
HubspotServiceV2
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 6
462
0.00% covered (danger)
0.00%
0 / 1
 batchUpdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendToHusbpot
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
30
 sendToHubspot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendToHubspotSafe
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 updateHubspotOptOutProperty
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
20
 createHubspotProperties
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace App\Http\Services;
4
5use HubSpot\Factory;
6use App\Http\Models\Auth\User;
7use App\Http\Models\HubspotFailedSync;
8use App\Jobs\ProcessHubspotAsyncJob;
9use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectInput;
10use Illuminate\Support\Facades\Log;
11use Illuminate\Support\Facades\Config;
12use HubSpot\Client\Crm\Contacts\ApiException;
13use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectBatchInput;
14use HubSpot\Client\Crm\Contacts\Model\BatchInputSimplePublicObjectBatchInput;
15use Illuminate\Support\Facades\Http;
16use HubSpot\Discovery\Discovery;
17
18class HubspotServiceV2
19{
20    /**
21     * To update multiple properties for a single user
22     */
23    public function batchUpdate($hubspotId, array $properties = [])
24    {
25        ProcessHubspotAsyncJob::dispatch($hubspotId, $properties);
26    }
27
28    public function sendToHusbpot(string $hubspotId, array $properties, bool $safe = true): void
29    {
30        $user = User::firstWhere('hubspot_id', $hubspotId);
31
32        if (config("app.env") != "production") {
33            $email = $user?->email ?? $hubspotId;
34            Log::info("Faking hubspot update for {$email}", $properties);
35            return;
36        }
37
38        if (empty($hubspotId) || empty($properties)) {
39            return;
40        }
41
42        $client = Factory::createWithAccessToken(config('hubspotconfig.access_token'));
43
44        $batchInputSimplePublicObjectBatchInput = new BatchInputSimplePublicObjectBatchInput([
45            'inputs' => [
46                new SimplePublicObjectBatchInput([
47                    'properties' => $properties,
48                    'id' => $hubspotId
49                ])
50            ],
51        ]);
52
53        if ($safe) {
54            $this->sendToHubspotSafe($client, $batchInputSimplePublicObjectBatchInput, $user, $hubspotId, $properties);
55        } else {
56            $this->sendToHubspot($client, $batchInputSimplePublicObjectBatchInput);
57        }
58    }
59
60    private function sendToHubspot(
61        Discovery $client,
62        BatchInputSimplePublicObjectBatchInput $batchInputSimplePublicObjectBatchInput
63    ) {
64        $client->crm()->contacts()->batchApi()->update($batchInputSimplePublicObjectBatchInput);
65    }
66
67    private function sendToHubspotSafe(
68        Discovery $client,
69        BatchInputSimplePublicObjectBatchInput $batchInputSimplePublicObjectBatchInput,
70        User $user,
71        string $hubspotId,
72        array $properties,
73    ) {
74        try {
75            $this->sendToHubspot($client, $batchInputSimplePublicObjectBatchInput);
76        } catch (ApiException $e) {
77            HubspotFailedSync::create([
78                'user_id' => $user?->id ?? null,
79                'email' => $user?->email ?? null,
80                'hubspot_id' => $hubspotId,
81                'data' => json_encode($properties),
82                'error' => $e->getMessage(),
83            ]);
84        }
85    }
86
87
88    public function updateHubspotOptOutProperty($email)
89    {
90        if (config("app.env") != "production") {
91            return;
92        }
93
94        try {
95            $accessToken = Config::get('hubspotconfig.access_token');
96            $url = "https://api.hubapi.com/communication-preferences/v4/statuses/{$email}/unsubscribe-all?verbose=false&channel=EMAIL&optState=OPT_OUT";
97
98            $data = [
99                'optState' => 'OPT_OUT',
100            ];
101
102            $response = Http::withHeaders([
103                'Authorization' => "Bearer {$accessToken}",
104                'Content-Type' => 'application/json',
105            ])->post($url, $data);
106
107            if ($response->successful()) {
108                Log::info("Unsubscribed {$email} from all emails.");
109            } else {
110                Log::error("Failed to unsubscribe {$email}", [
111                    'status' => $response->status(),
112                    'response' => $response->body(),
113                ]);
114            }
115        } catch (\Exception $e) {
116            Log::error("Exception in updateHubspotOptOutProperty: " . $e->getMessage());
117        }
118    }
119
120    public function createHubspotProperties(User $user)
121    {
122        if (config("app.env") != "production") {
123            $fakeHubspotId = $user->email;
124
125            User::where(['email' => $user->email])->update(['hubspot_id' => $fakeHubspotId]);
126
127            return;
128        }
129
130        $user_contact_hubspot = [
131            'firstname' => $user->first_name,
132            'lastname' => $user->last_name,
133            'email' => $user->email,
134            'email_used_for_login' => $user->email,
135            'flymsg_id' => $user->id,
136            'signup_source' => $user->signup_source,
137        ];
138
139        if ($user->account_creation_date) {
140            // existing user
141            $user_contact_hubspot['account_creation_date'] = $user->account_creation_date;
142            $user_contact_hubspot['flymsg_id'] = $user->id;
143            $user_contact_hubspot['signup_source'] = $user->signup_source;
144        } else {
145            // new user
146            $user_contact_hubspot['account_creation_date'] = date('Y-m-d', strtotime('today midnight'));
147        }
148
149        $date_only = $user->created_at ?? $user->updated_at ?? now();
150        $date_only = explode(' ', $date_only->toDateTime()->format('Y-m-d'));
151        $createdTimestamp = \Carbon\Carbon::parse($date_only[0])->toDateString();
152        $user_contact_hubspot['df_stripe_customer_id'] = $user->stripe_id;
153        $user_contact_hubspot['freemium_subscription_start_date'] = $createdTimestamp;
154        $user_contact_hubspot['freemium_subscription_status_updated_on'] = $createdTimestamp;
155        $user_contact_hubspot['flymsg_freemium_subscription_status'] = 'Active';
156        $user_contact_hubspot['subscription_type'] = empty($user->email_verified_at) ? 'Unverified' : 'Freemium';
157
158        $field_name = 'email';
159        $searchRequest = array(
160            "filterGroups" => [array(
161                "filters" => [array(
162                    "value" => $user->email,
163                    "propertyName" => $field_name,
164                    "operator" => "EQ",
165                )],
166            )],
167        );
168
169        $client = Factory::createWithAccessToken(config('hubspotconfig.access_token'));
170        $apiResponse = $client->crm()->contacts()->searchApi()->doSearch($searchRequest);
171
172        if (isset($apiResponse["total"]) && $apiResponse["total"] > 0) {
173            $response = $apiResponse["results"][0];
174            $hubspot_id = $response["id"];
175            User::where(['email' => $user->email])->update(['hubspot_id' => $hubspot_id]);
176        } else {
177            $user = User::firstWhere('email', $user->email);
178            if (!$user || empty($user->hubspot_id)) {
179                $simplePublicObjectInputForCreate = new SimplePublicObjectInput([
180                    'properties' => $user_contact_hubspot,
181                ]);
182
183                $client = Factory::createWithAccessToken(config('hubspotconfig.access_token'));
184                $apiResponse = $client->crm()->contacts()->basicApi()->create($simplePublicObjectInputForCreate);
185                User::where(['email' => $user->email])->update(['hubspot_id' => $apiResponse['id']]);
186            }
187        }
188    }
189}