Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 187
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
InstancyServiceV2
0.00% covered (danger)
0.00%
0 / 187
0.00% covered (danger)
0.00%
0 / 10
1806
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 createInstancyUser
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 1
132
 updateMembership
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 1
132
 userMembershipDetails
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUserDetailsByEmailForAllSites
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 validateUser
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 authenticateUser
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
 generateSessionID
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 callInstancyApi
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 hasError
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Services;
4
5use Carbon\Carbon;
6use Illuminate\Support\Str;
7use App\Http\Models\Auth\User;
8use Illuminate\Support\Facades\Http;
9use App\Exceptions\ExpectedException;
10use App\Http\Models\Admin\Company;
11use App\Http\Models\Admin\CompanyGroup;
12
13class InstancyServiceV2
14{
15    private $astrKey;
16    private $url;
17    private $sso_url;
18    private $siteGroupId;
19    private $action;
20    private $uniquePassword;
21
22    public function __construct()
23    {
24        $this->url = "https://ondemand-admin.vengreso.com/InstancyService.asmx";
25        $this->sso_url = "https://ondemand-master-admin.vengreso.com/InstancyService.asmx";
26        $this->astrKey = "22A9838A-2196-47ED-8126-4321B7A07EF1";
27        $this->siteGroupId = "388";
28        $this->uniquePassword = '17$5I$jaFq@';
29
30        if (!isProduction() && !isLocalProduction()) {
31            $this->url = "https://ondemand-admin.instancy.net/instancyservice.asmx";
32            $this->sso_url = "https://ondemand-master-admin.instancy.net/InstancyService.asmx";
33            $this->astrKey = "A58ABE98-1B0D-41FC-9805-0F34D6B99E80";
34        }
35    }
36
37    /**
38     * Create Instancy User
39     *
40     *
41     * @return mixed
42     */
43    public function createInstancyUser(string $email, string $groupId): array
44    {
45        $user = User::whereEmail($email)->first();
46        if (!$user) {
47            return ["Error" => "User not found"];
48        }
49        $First_Name = str_replace("'", " ", $user->first_name);
50        $Last_Name = str_replace("'", " ", $user->last_name);
51        $this->action = "CreateUser";
52
53        $parentId = $this->siteGroupId;
54
55        if ($groupId) {
56            $parentId = $groupId;
57        }
58
59        // Get the users subscription data.
60        // We are assuming that all the users have subscription records
61        // since this is only for pro users.
62        $subscription = $user->subscription("main");
63
64        if (!$subscription) {
65            throw new ExpectedException("The user with email $email needs to have an active subscription");
66        }
67
68        $end_date = Carbon::parse($subscription->ends_at)->toDateString();
69        $start_date = $subscription->created_at->toDateString();
70
71        if ($subscription->stripe_status == "trialing") {
72            $end_date = Carbon::parse($subscription->trial_ends_at)->toDateString();
73        }
74
75        $MembershipType = "Annual";
76        $MembershipDurationID = 30; // Sales pro yearly
77
78        if ($subscription->plan && $subscription->plan->identifier == "sales-pro-monthly") {
79            $MembershipType = "Non-Annual";
80            $MembershipDurationID = 32; // Sales pro yearly
81        }
82
83        $instancyEmail = $email;
84
85        if (!isProduction() && !isLocalProduction()) {
86            $instancyEmail = 'staging.' . $email;
87        }
88
89        $xml = "<?xml version='1.0' encoding='iso-8859-1'?>
90        <InstancyWrapper>
91            <Request SiteID='$this->siteGroupId'>
92                <UserDetails>
93                    <GroupID><![CDATA[$parentId]]></GroupID>
94                    <First_Name><![CDATA[$First_Name]]></First_Name>
95                    <Gender><![CDATA[1]]></Gender>
96                    <Last_Name><![CDATA[$Last_Name]]></Last_Name>
97                    <User_name><![CDATA[$instancyEmail]]></User_name>
98                    <Email><![CDATA[$instancyEmail]]></Email>
99                    <Password><![CDATA[FlyMSGWelcome#2024]]></Password>
100                    <Mobile_Number><![CDATA[0000000000]]></Mobile_Number>
101                    <Job_title>User</Job_title>
102                    <Company_Name>Vengreso</Company_Name>
103                    <MembershipDurationID>$MembershipDurationID</MembershipDurationID>
104                    <PaymentType><![CDATA[Credit Card]]></PaymentType>
105                </UserDetails>
106            </Request>
107        </InstancyWrapper>";
108
109        $response = $this->callInstancyApi($xml);
110        $response = parseInstancyXml($response);
111
112        $response = parseInstancyXml($response["value"]);
113        $response_status = $response['Response'][0]["@attributes"]["Result"];
114
115        if ($response_status == "Success") {
116            // Update the user profile with the instancy ID
117            $instancy_id = $response["UserDetails"][0]["UserID"][0]["value"];
118            $user->instancy_id = $instancy_id;
119            $user->save();
120
121            $response["FlyMSGUser"] = [
122                "InstancyID" => $instancy_id,
123                "Email" => $email
124            ];
125        } else {
126            $result = $this->getUserDetailsByEmailForAllSites($email);
127            $result_status = $result['Response'][0]["@attributes"]["Result"];
128            if ($result_status == "Success") {
129                // Get the user id and save it to the DB user profile
130                $instancy_id = $result['UserDetails'][0]['UserID'][0]['value'];
131                $response["FlyMSGUser"] = [
132                    "InstancyID" => $instancy_id,
133                    "Email" => $email
134                ];
135            }
136        }
137
138        return $response;
139    }
140
141    /**
142     * Update Membership on instancy.
143     * Used mostly to update the users membership expiry date.
144     * If a param $date is passed, it will be used as the new expiry date.
145     *
146     * @param   string  $email
147     * @param   string  $date of expiry
148     *
149     * @return  array
150     */
151    public function updateMembership($email, $date = null): array
152    {
153        $user = User::withTrashed()->whereEmail($email)->first();
154        $group = CompanyGroup::find($user->company_group_id);
155        $company = Company::find($user->company_id);
156
157        $groupId = false;
158        if ($group) {
159            $groupId = $group->instancy_id;
160        } elseif ($company) {
161            $groupId = $company->instancy_id;
162        }
163
164        if (!$user) {
165            return ["Error" => "User not found"];
166        }
167
168        $instancy_id = $user->instancy_id;
169        if (!$instancy_id) {
170            $result = $this->getUserDetailsByEmailForAllSites($email);
171            $result_status = $result['Response'][0]["@attributes"]["Result"];
172            if ($result_status == "Success") {
173                // Get the user id and save it to the DB user profile
174                $instancy_id = $result['UserDetails'][0]['UserID'][0]['value'];
175                $user->instancy_id = $instancy_id;
176                $user->save();
177            } else {
178                $this->createInstancyUser($email, $groupId);
179                $result = $this->getUserDetailsByEmailForAllSites($email);
180                $result_status = $result['Response'][0]["@attributes"]["Result"];
181                if ($result_status == "Success") {
182                    // Get the user id and save it to the DB user profile
183                    $instancy_id = $result['UserDetails'][0]['UserID'][0]['value'];
184                    $user->instancy_id = $instancy_id;
185                    $user->save();
186                }
187            }
188        }
189
190        // Get the users subscription data.
191        // We are assuming that all the users have subscription records
192        // since this is only for pro users.
193        $subscription = $user->subscription("main");
194
195        $end_date = Carbon::parse($subscription->ends_at)->toDateString();
196        $start_date = $subscription->created_at->toDateString();
197
198        if ($subscription->stripe_status == "trialing") {
199            $end_date = Carbon::parse($subscription->trial_ends_at)->toDateString();
200        }
201
202        if ($subscription->stripe_status != "active" && $subscription->stripe_status != "trialing") {
203            // If not active, expire it by setting the expiry date to a day before
204            // today.
205            $end_date = Carbon::now()->toDateString();
206        }
207
208        $this->action = 'UpdateMemebrship';
209        $siteID = $this->siteGroupId;
210        $end_date = $date ?? $end_date;
211
212        $DurationName = "One Year";
213        $MembershipType = "Annual";
214        $MembershipDurationID = 30; // Sales pro yearly
215
216        if ($subscription->plan?->identifier == "sales-pro-monthly") {
217            $DurationName = "One Month";
218            $MembershipType = "Non-Annual";
219            $MembershipDurationID = 32; // Sales pro yearly
220        }
221
222        $xml = "<?xml version='1.0' encoding='iso-8859-1'?>
223        <InstancyWrapper>
224            <Request SiteID='$siteID'>
225                <UpdateMemebrship>
226                    <MembershipID>40</MembershipID>
227                    <UserID>$instancy_id</UserID>
228                    <ExpiryDate>$end_date</ExpiryDate>
229                    <StartDate>$start_date</StartDate>
230                    <DurationName>$DurationName</DurationName>
231                    <MembershipDurationID>$MembershipDurationID</MembershipDurationID>
232                    <RecurringProfileID></RecurringProfileID>
233                    <Paymentmode>Exempted</Paymentmode>
234                    <Notes></Notes>
235                    <Amount>0</Amount>
236                </UpdateMemebrship>
237            </Request>
238        </InstancyWrapper>";
239        $response = $this->callInstancyApi($xml);
240        $response = parseInstancyXml($response);
241        $response = parseInstancyXml($response["value"]);
242        $response["FlyMSGUser"] = [
243            "InstancyID" => $instancy_id,
244            "Email" => $email
245        ];
246
247        return $response;
248    }
249
250    /**
251     * function to get the user membership details
252     */
253    public function userMembershipDetails($data): array
254    {
255        return $this->getUserDetailsByEmailForAllSites($data['email']);
256    }
257
258    /**
259     * Get Membership Details by Email
260     * Use this to get the details about the user and the membership
261     * but mostly to get the USER ID to backfill the missing
262     * ones on flymsg DB.
263     *
264     * @param   string  $email
265     *
266     * @return  array $response
267     */
268    public function getUserDetailsByEmailForAllSites($email): array
269    {
270        $user = User::whereEmail($email)->first();
271        if (!$user) {
272            return ["Error" => "User not found"];
273        }
274
275        $instancy_id = $user->instancy_id;
276
277        $instancyEmail = $email;
278
279        if (!isProduction() && !isLocalProduction()) {
280            $instancyEmail = 'staging.' . $email;
281        }
282
283        $this->action = 'GetUserInfoByEmailForAllSites';
284        $siteID = $this->siteGroupId;
285        $xml = "<?xml version='1.0' encoding='iso-8859-1'?><InstancyWrapper><Request SiteID='$siteID'/><UserDetails><email><![CDATA[$instancyEmail]]></email></UserDetails></InstancyWrapper>";
286        $response = $this->callInstancyApi($xml);
287        $response = parseInstancyXml($response);
288        $response = parseInstancyXml($response["value"]);
289        $response["FlyMSGUser"] = [
290            "InstancyID" => $instancy_id,
291            "Email" => $email
292        ];
293        return $response;
294    }
295
296    public function validateUser(string $email): bool
297    {
298        $response = $this->getUserDetailsByEmailForAllSites($email);
299        return $this->hasError($response);
300    }
301
302    public function authenticateUser(string $email)
303    {
304        $response = $this->generateSessionID($email);
305
306        if ($this->hasError($response)) {
307            if (
308                $response["Response"][0]["@attributes"]["ResultDescription"] != "User Membership Expired" &&
309                $response["Response"][0]["@attributes"]["ResultDescription"] != "Account Deactivated"
310            ) {
311                // Attempt to create the user and authenticate again
312                // this preserves the old api.
313
314                $user = User::firstWhere('email', $email);
315                $group = CompanyGroup::find($user->company_group_id);
316                $company = Company::find($user->company_id);
317
318                $groupId = false;
319                if ($company) {
320                    $groupId = $company->instancy_id;
321                } elseif ($group) {
322                    $groupId = $group->instancy_id;
323                }
324
325                $this->createInstancyUser($email, $groupId);
326                $response = $this->authenticateUser($email);
327                // Handle authentication error
328                return $response; // Or throw an exception
329            }
330        }
331        return $response;
332    }
333
334    private function generateSessionID($email)
335    {
336        $api = $this->sso_url . '/AuthenticateUser';
337        $siteID = $this->siteGroupId;
338
339        $instancyEmail = $email;
340
341        if (!isProduction() && !isLocalProduction()) {
342            $instancyEmail = 'staging.' . $email;
343        }
344
345        $data = "<?xml version='1.0' encoding='iso-8859-1'?><InstancyWrapper><Request SiteID='$siteID'><UserDetails><UserID><![CDATA[-1]]></UserID><Email><![CDATA[$instancyEmail]]></Email><Password><![CDATA[$this->uniquePassword]]></Password></UserDetails></Request></InstancyWrapper>";
346        $response = Http::withHeaders([
347            'Cookie' => 'ASP.NET_SessionId=fuhbkztcn41q4vteeipt5jmr',
348            'Accept-Encoding' => '',
349        ])->asForm()
350            ->post($api, [
351                'astrKey' => $this->astrKey,
352                'astrXML' => $data,
353            ]);
354
355        $email = urlencode($email);
356
357        $response = parseInstancyXml($response->body());
358        $response = parseInstancyXml($response["value"]);
359
360        return $response;
361    }
362
363    private function callInstancyApi($xml)
364    {
365        $url = $this->url . '/' . $this->action;
366        $response = Http::withHeaders([
367            'Accept-Encoding' => '',
368            'Content-Type' => 'application/x-www-form-urlencoded',
369        ])->asForm()
370            ->post($url, [
371                'astrKey' => $this->astrKey,
372                'astrXML' => $xml,
373            ])->body();
374        return $response;
375    }
376
377    public function hasError($response)
378    {
379        return Str::contains(json_encode($response), ['Invalid User ID', 'Invalid Client ID', 'There is no row', 'Error']);
380    }
381}