Skip to content

Commit 77b38f6

Browse files
email octopus and banner
1 parent 1fd6c04 commit 77b38f6

8 files changed

Lines changed: 661 additions & 12 deletions

File tree

app/Http/Controllers/LeadsController.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
use App\Events\LeadRegistered;
66
use App\Models\Leads;
77
use App\Services\Mail\EmailOctopusService;
8+
use App\Services\Mail\EmailOctopusV2Service;
89
use Illuminate\Http\Request;
10+
use Illuminate\Support\Str;
911
use Illuminate\Validation\ValidationException;
1012

1113
class LeadsController extends Controller
@@ -26,9 +28,19 @@ public function create(Request $request)
2628
]
2729
);
2830

29-
$emailOctopus = new EmailOctopusService();
31+
$tags = $request->input('tags', []);
32+
$primaryTag = $tags[0] ?? null;
33+
34+
$emailOctopus = $this->shouldUseEmailOctopusV2($tags)
35+
? new EmailOctopusV2Service()
36+
: new EmailOctopusService();
37+
3038
$existingLead = Leads::where('email', $request->email)->first();
31-
$existingLeadByTag = Leads::where('email', $request->email)->where('tag', $request->tags[0])->first();
39+
$existingLeadByTag = $primaryTag === null
40+
? null
41+
: Leads::where('email', $request->email)
42+
->where('tag', $primaryTag)
43+
->first();
3244

3345
if ($existingLeadByTag) {
3446
return response()->json(['error' => 'Esse e-mail já foi cadastrado anteriormente.'], 409);
@@ -38,7 +50,7 @@ public function create(Request $request)
3850
$lead->email = $request->email;
3951
$lead->name = $request->name;
4052
$lead->phone = $request->phone;
41-
$lead->tag = $request->tags[0];
53+
$lead->tag = $primaryTag;
4254
$lead->save();
4355

4456
if ($existingLead) {
@@ -65,4 +77,15 @@ public function create(Request $request)
6577
return response()->json(['error' => $errors], $status);
6678
}
6779
}
80+
81+
private function shouldUseEmailOctopusV2(array $tags): bool
82+
{
83+
foreach ($tags as $tag) {
84+
if (is_string($tag) && Str::startsWith($tag, 'curso-ao-vivo-codando-com-ia')) {
85+
return true;
86+
}
87+
}
88+
89+
return false;
90+
}
6891
}

app/Http/Controllers/PagarmeController.php

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,189 @@
1010
use Illuminate\Http\Request;
1111
use Illuminate\Support\Facades\Auth;
1212
use Illuminate\Support\Facades\Http;
13+
use Illuminate\Support\Str;
1314
use Mail;
1415

1516
class PagarmeController extends Controller
1617
{
18+
private const CODANDO_COM_IA_PRICE_IN_CENTS = 58800;
19+
private const CODANDO_COM_IA_PRODUCT_SLUG = 'curso-ao-vivo-codando-com-ia-v1';
20+
1721
public function __construct()
1822
{
19-
$this->middleware('auth:sanctum');
23+
$this->middleware('auth:sanctum')->only([
24+
'createOrderAndGetCheckoutLink',
25+
'getSubscriptionByPagarmeOrderId',
26+
]);
27+
}
28+
29+
public function createCodandoComIaCheckout(Request $request)
30+
{
31+
$validated = $request->validate([
32+
'name' => 'required|string|max:255',
33+
'email' => 'required|email',
34+
'phone' => 'required|string|max:30',
35+
'tag' => 'nullable|string|max:255',
36+
]);
37+
38+
$rawPhone = preg_replace('/\D/', '', $validated['phone']);
39+
40+
if (Str::startsWith($rawPhone, '55') && strlen($rawPhone) > 11) {
41+
$rawPhone = substr($rawPhone, 2);
42+
}
43+
44+
$phonesPayload = null;
45+
46+
if (strlen($rawPhone) >= 10) {
47+
$areaCode = substr($rawPhone, 0, 2);
48+
$number = substr($rawPhone, 2);
49+
50+
$phonesPayload = [
51+
'country_code' => '55',
52+
'area_code' => $areaCode,
53+
'number' => $number,
54+
];
55+
}
56+
57+
$customerPayload = [
58+
'name' => $validated['name'],
59+
'email' => $validated['email'],
60+
'type' => 'individual',
61+
'metadata' => [
62+
'product_slug' => self::CODANDO_COM_IA_PRODUCT_SLUG,
63+
'lead_tag' => $validated['tag'] ?? null,
64+
],
65+
];
66+
67+
if ($phonesPayload) {
68+
$customerPayload['phones'] = [
69+
'mobile_phone' => $phonesPayload,
70+
];
71+
}
72+
73+
$installments = collect(range(1, 12))->map(function ($number) {
74+
return [
75+
'number' => $number,
76+
'total' => self::CODANDO_COM_IA_PRICE_IN_CENTS,
77+
];
78+
})->values()->all();
79+
80+
$checkoutPayload = [
81+
'code' => 'codando-com-ia-'.Str::uuid()->toString(),
82+
'customer' => $customerPayload,
83+
'items' => [
84+
[
85+
'id' => 'codando-com-ia',
86+
'amount' => self::CODANDO_COM_IA_PRICE_IN_CENTS,
87+
'description' => 'Curso Codando com IA - Compra Única',
88+
'quantity' => 1,
89+
'code' => self::CODANDO_COM_IA_PRODUCT_SLUG,
90+
],
91+
],
92+
'payments' => [
93+
[
94+
'payment_method' => 'checkout',
95+
'checkout' => [
96+
'customer_editable' => true,
97+
'accepted_payment_methods' => [
98+
'credit_card',
99+
'boleto',
100+
'pix',
101+
],
102+
'success_url' => config('app.frontend_url').'/curso-ao-vivo/codando-com-ia/sucesso',
103+
'pix' => [
104+
'expires_in' => 86400,
105+
],
106+
'boleto' => [
107+
'due_at' => Carbon::now()
108+
->addDays(3)
109+
->toIso8601String(),
110+
],
111+
'credit_card' => [
112+
'installments' => $installments,
113+
'operation_type' => 'auth_and_capture',
114+
],
115+
],
116+
],
117+
],
118+
'metadata' => [
119+
'product_slug' => self::CODANDO_COM_IA_PRODUCT_SLUG,
120+
'lead_phone' => $validated['phone'],
121+
'lead_tag' => $validated['tag'] ?? null,
122+
'lead_email' => $validated['email'],
123+
'lead_name' => $validated['name'],
124+
'lead_phone_digits' => $phonesPayload
125+
? $phonesPayload['area_code'].$phonesPayload['number']
126+
: null,
127+
],
128+
];
129+
130+
$response = Http::withBasicAuth(
131+
config('services.pagarme.api_key'),
132+
''
133+
)->post('https://api.pagar.me/core/v5/orders', $checkoutPayload);
134+
135+
if ($response->failed()) {
136+
$status = $response->status();
137+
$errorPayload = $response->json();
138+
139+
logger()->error('Pagarme order checkout creation failed', [
140+
'status' => $status,
141+
'payload' => $checkoutPayload,
142+
'response' => $errorPayload,
143+
'response_body' => $response->body(),
144+
]);
145+
146+
return response()->json([
147+
'message' => 'Não foi possível iniciar o checkout no momento.',
148+
'details' => $errorPayload,
149+
], $status > 0 ? $status : 400);
150+
}
151+
152+
$order = $response->json();
153+
154+
return [
155+
'checkoutLink' => $order['checkouts'][0]['payment_url'] ?? null,
156+
'pagarmeOrderID' => $order['id'] ?? null,
157+
'amount' => $order['amount'] ?? self::CODANDO_COM_IA_PRICE_IN_CENTS,
158+
'status' => $order['status'] ?? null,
159+
];
160+
}
161+
162+
public function getCodandoComIaOrderStatus(string $orderId)
163+
{
164+
$endpoint = "https://api.pagar.me/core/v5/orders/{$orderId}";
165+
166+
$response = Http::withBasicAuth(
167+
config('services.pagarme.api_key'),
168+
''
169+
)->get($endpoint);
170+
171+
if ($response->failed()) {
172+
$status = $response->status();
173+
174+
return response()->json([
175+
'message' => 'Não foi possível recuperar o status do pedido.',
176+
], $status > 0 ? $status : 400);
177+
}
178+
179+
$order = $response->json();
180+
$productSlug = $order['metadata']['product_slug'] ?? null;
181+
182+
if ($productSlug !== self::CODANDO_COM_IA_PRODUCT_SLUG) {
183+
return response()->json(['message' => 'Pedido não encontrado'], 404);
184+
}
185+
186+
return [
187+
'id' => $order['id'] ?? null,
188+
'status' => $order['status'] ?? null,
189+
'amount' => $order['amount'] ?? null,
190+
'charges' => $order['charges'] ?? [],
191+
'customer' => [
192+
'name' => $order['customer']['name'] ?? null,
193+
'email' => $order['customer']['email'] ?? null,
194+
],
195+
];
20196
}
21197

22198
public function createOrderAndGetCheckoutLink(Request $request)

app/Http/Controllers/PagarmeWebhooks.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
class PagarmeWebhooks
2020
{
21+
private const CODANDO_COM_IA_PRODUCT_SLUG = 'curso-ao-vivo-codando-com-ia-v1';
22+
2123
public function handleWebhook(Request $request)
2224
{
2325
$eventType = $request->post('type');
@@ -42,6 +44,18 @@ public function handleWebhook(Request $request)
4244
)->first();
4345

4446
if (! $subscription) {
47+
$orderMetadata = $request->post('data')['metadata']['product_slug'] ?? null;
48+
$customerMetadata = $request->post('data')['customer']['metadata']['product_slug'] ?? null;
49+
50+
if (
51+
$orderMetadata === self::CODANDO_COM_IA_PRODUCT_SLUG ||
52+
$customerMetadata === self::CODANDO_COM_IA_PRODUCT_SLUG
53+
) {
54+
Discord::sendMessage("Webhook recebido para pedido {$pagarmeOrderId} do produto Codando com IA (fluxo sem subscription)", 'notificacoes-compras');
55+
56+
return new Response();
57+
}
58+
4559
Discord::sendMessage("Erro, não há subscription com o id {$pagarmeOrderId}", 'notificacoes-compras');
4660

4761
return new Response();

app/Services/Mail/EmailOctopusService.php

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,52 @@ public function __construct()
1818

1919
public function registerEmailOctopusContact($email, $fields, $tags = [])
2020
{
21-
Http::post(
21+
// Convert tags array to object format expected by API
22+
// ['tag1', 'tag2'] becomes ['tag1' => true, 'tag2' => true]
23+
$tagsObject = [];
24+
foreach ($tags as $tag) {
25+
$tagsObject[$tag] = true;
26+
}
27+
28+
Http::contentType('application/json')->post(
2229
"https://emailoctopus.com/api/1.6/lists/$this->listId/contacts",
2330
[
2431
'api_key' => $this->api_key,
2532
'email_address' => $email,
2633
'fields' => $fields,
27-
'tags' => $tags,
34+
'tags' => $tagsObject,
2835
]
2936
);
3037
}
3138

3239
public function updateEmailOctopusContact($email, $fields, $tags = [])
3340
{
3441
$emailHash = md5(strtolower(trim($email)));
35-
Http::put(
42+
43+
// Convert tags array to object format expected by API
44+
// ['tag1', 'tag2'] becomes ['tag1' => true, 'tag2' => true]
45+
$tagsObject = [];
46+
foreach ($tags as $tag) {
47+
$tagsObject[$tag] = true;
48+
}
49+
50+
$payload = [
51+
'api_key' => $this->api_key,
52+
];
53+
54+
// Only add fields if not empty
55+
if (! empty($fields)) {
56+
$payload['fields'] = $fields;
57+
}
58+
59+
// Only add tags if not empty
60+
if (! empty($tagsObject)) {
61+
$payload['tags'] = $tagsObject;
62+
}
63+
64+
Http::contentType('application/json')->put(
3665
"https://emailoctopus.com/api/1.6/lists/$this->listId/contacts/$emailHash",
37-
[
38-
'api_key' => $this->api_key,
39-
'fields' => $fields,
40-
'tags' => $tags,
41-
]
66+
$payload
4267
);
4368
}
4469

0 commit comments

Comments
 (0)