Lib.WhatsAppMeta
1.0.48
dotnet add package Lib.WhatsAppMeta --version 1.0.48
NuGet\Install-Package Lib.WhatsAppMeta -Version 1.0.48
<PackageReference Include="Lib.WhatsAppMeta" Version="1.0.48" />
<PackageVersion Include="Lib.WhatsAppMeta" Version="1.0.48" />
<PackageReference Include="Lib.WhatsAppMeta" />
paket add Lib.WhatsAppMeta --version 1.0.48
#r "nuget: Lib.WhatsAppMeta, 1.0.48"
#:package Lib.WhatsAppMeta@1.0.48
#addin nuget:?package=Lib.WhatsAppMeta&version=1.0.48
#tool nuget:?package=Lib.WhatsAppMeta&version=1.0.48
Lib.WhatsAppMeta
A .NET library for integrating with the WhatsApp Business API (Meta). It provides a ready-to-use service for sending template messages, creating templates (including with media), uploading media, webhook verification and processing, and persisting WhatsApp-related data via Entity Framework Core. Designed to work both in the same solution and when installed as a package in another project.
Table of contents
- Features
- Installation
- Install in another project (new version) — prompt/checklist for media URLs and optional SignalR
- Quick start
- Service registration
- Configuration
- Using the service
- API reference
- Webhook (Meta callback)
- Realtime / SignalR (optional)
- CRM template sending (SendTemplateMessageCrm)
- Creating message templates
- Entities and DbContext
- Data insert and webhook in any project
- Database setup and migrations
- Stored procedures (refresh SQL in another project)
- SQL Files Guide
- Requirements
- Troubleshooting
Features
- WhatsApp Meta API – Send template messages, create templates, upload media, manage business account
- Entity Framework Core – DbContext and entities for credentials, templates, message list, webhook message status
- Custom schema – Tables can use a SQL schema (e.g.
crm.MessageTemplates) - CRM bulk sending –
SendTemplateMessageCrmwith template lookup, image upload, and send-list persistence - Webhook – Verify Meta webhook (GET) and process incoming messages, status updates, and history (POST). Optional default processor persists to the same DbContext; you can replace it with your own. Register
AddWhatsAppMediaDownloader()(and optionallyIWhatsAppBaseUrlProvider) so incoming media gets a public URL instead of blank when using the package in another project. - Audit fields (optional) –
IWhatsAppMetaUserIdProviderfor CreatedBy/UpdatedBy/DeletedBy; works without it in another project (inserts still succeed) - Dependency injection – Designed for ASP.NET Core / any host with DI; works when used as a NuGet package in another solution
Installation
NuGet
dotnet add package Lib.WhatsAppMeta
Project reference (same solution)
<ProjectReference Include="path\to\Lib.WhatsAppMeta.csproj" />
Quick start
- Register services (e.g. in
Program.csor your DI configuration):
using Lib.WhatsAppMeta.Extensions;
// Uses connection string named "db" from IConfiguration
builder.Services.AddWhatsAppMeta(builder.Configuration);
// Optional: webhook verify token (required if you expose a webhook endpoint)
builder.Services.AddWhatsAppMetaWebhook("YourVerifyToken");
// Optional: install DB objects (tables, schema) on startup
builder.Services.UseWhatsAppMetaMigrations();
- Inject and use the service (always use the interface):
using Lib.WhatsAppMeta.Services;
public class MyHandler
{
private readonly IWhatsappMetaService _whatsappMetaService;
public MyHandler(IWhatsappMetaService whatsappMetaService)
{
_whatsappMetaService = whatsappMetaService;
}
public async Task DoSomething()
{
var response = await _whatsappMetaService.SendTemplateMessage(
jsonPayload, accessToken, CancellationToken.None);
}
}
Service registration
AddWhatsAppMeta (extension methods)
| Overload | Use when |
|---|---|
AddWhatsAppMeta(IConfiguration, connectionStringName?, schema?) |
You want to read the connection string from configuration (e.g. ConnectionStrings:db). |
AddWhatsAppMeta(string connectionString, schema?) |
You have the connection string in code or from another source. |
Parameters
- connectionStringName – Key in
IConfiguration(default:"db") →configuration.GetConnectionString("db"). - schema – SQL schema for tables (e.g.
"crm"→crm.MessageTemplates). Optional; if omitted, default schema is used. - connectionString – Full SQL Server connection string (second overload).
Examples
using Lib.WhatsAppMeta.Extensions;
// Default: connection string "db", default schema
builder.Services.AddWhatsAppMeta(builder.Configuration);
// Custom connection string key and schema "crm"
builder.Services.AddWhatsAppMeta(builder.Configuration, "db", "crm");
// Direct connection string and schema
builder.Services.AddWhatsAppMeta(
"Server=.;Database=MyDb;Integrated Security=true;TrustServerCertificate=true",
"crm");
What gets registered
IWhatsappMetaService→WhatsappMetaService(scoped)WhatsAppMetaDbContext(scoped), when a non-empty connection string is providedIWhatsAppWebhookService→WhatsAppWebhookService(scoped)IWhatsAppWebhookProcessor→DefaultWhatsAppWebhookProcessor(scoped), unless you register your own (your registration wins)IWhatsAppMetaUserIdProvider→HttpContextUserIdProviderAdapter(scoped, optional bridge for audit fields)
AddWhatsAppMetaWebhook (verify token)
Call after AddWhatsAppMeta when you expose a webhook URL for Meta to call:
| Parameter | Description |
|---|---|
verifyToken |
Token Meta sends as hub.verify_token on GET; set per project (e.g. "WAVerifytokenJMS"). |
builder.Services.AddWhatsAppMetaWebhook("YourVerifyToken");
Configuration
appsettings.json
Connection string (required for DB and migrations):
{
"ConnectionStrings": {
"db": "Server=localhost;Database=YourDb;User Id=sa;Password=YourPassword;TrustServerCertificate=True;"
}
}
Facebook / WhatsApp (needed for CRM and template creation; exact section name can match your app):
{
"Facebook": {
"ClientId": "your-meta-app-client-id",
"ClientSecret": "...",
"GrantType": "..."
}
}
If you use the Lib’s built-in CRM providers (e.g. WhatsAppCrmClientIdProvider), bind this to Lib.Config.FaceBookSetting.FacebookSettings (or your settings type) and pass IOptions<FacebookSettings> where required.
Using the service
- Always depend on the interface
IWhatsappMetaService. Do not inject the concrete typeWhatsappMetaServicein application code.
// ✅ Correct
public MyService(IWhatsappMetaService whatsappMetaService) { }
// ❌ Wrong – can break DI in some setups
public MyService(WhatsappMetaService whatsappMetaService) { }
API reference
All methods are on IWhatsappMetaService (implemented by WhatsappMetaService).
| Method | Description |
|---|---|
SendTemplateMessage(string json, string accessToken, CancellationToken) |
Sends a template message using raw JSON payload. |
SendTemplateMessageCrm(SendTemplateMessageCrmRequest, SendTemplateMessageCrmCredential, IWhatsAppCrmSendContext, CancellationToken) |
Sends template messages in a CRM flow: template lookup, optional image upload, body/header params, location, and send-list persistence. Requires CRM context and providers to be registered. |
ProcessMediaUploadAsync(string mediaInput, string clientId, string phoneNumberId, string accessToken) |
Uploads media (e.g. base64 or URL) and returns a media ID. |
CreateMessageTemplate(CreateMessageTemplateRequest, string wabaId, string accessToken, CancellationToken) |
Creates a message template (no media upload). |
CreateMessageTemplateWithMedia(object commandRequest, string wabaId, string accessToken, string clientId, string phoneNumberId, ICreateTemplateContext?, MessageTemplateSaveOptions?, CancellationToken) |
Validates base64 size, uploads media, creates template, and optionally persists it via ICreateTemplateContext. |
FetchWhatsappBusinessAccount(string wabaId, string accessToken, CancellationToken) |
Fetches WhatsApp Business Account details. |
GetTemplateById / GetTemplateByIdAsString |
Gets a template by ID. |
GetAllTemplates(string wabaId, string accessToken, string? fields, int? limit, CancellationToken) |
Lists templates. |
RegisterPhoneNumber(string phoneNumberId, string pin, string codeMethod, string accessToken) |
Registers a phone number. |
SubscribeAppToWebhook(string wabaId, string accessToken) |
Subscribes app to webhook. |
SendMessageFromInbox(object commandRequest, string phoneNumberId, string accessToken, CancellationToken) |
Sends a message from inbox. Use SendMessageFromInboxRequest (in Lib.WhatsAppMeta.Models) for a shared request shape across projects. |
Request/response types live in Lib.WhatsAppMeta.Models and related namespaces (e.g. SendTemplateMessageCrmRequest, SendTemplateMessageCrmCredential, CreateMessageTemplateRequest, WhatsAppResponseModel, CreateMessageTemplateResult).
Webhook (Meta callback)
Meta sends GET requests to verify your webhook URL and POST requests with incoming messages, status updates, and history. The Lib handles verification and payload parsing; you expose a thin controller and optionally replace the default processor.
1. Set the verify token
builder.Services.AddWhatsAppMetaWebhook("YourVerifyToken"); // e.g. "WAVerifytokenJMS"
Use the same value in the Meta App Dashboard under Webhook Verify token.
2. Add a webhook controller
Inject IWhatsAppWebhookService. For GET, call VerifyWebhook and return the challenge when valid. For POST, read the raw body and call ProcessWebhookPayloadAsync; the Lib parses the payload and invokes your processor (or the default). Return 200 so Meta does not retry.
using Lib.WhatsAppMeta.Webhook;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class WhatsappWebhookController : ControllerBase
{
private readonly IWhatsAppWebhookService _webhookService;
public WhatsappWebhookController(IWhatsAppWebhookService webhookService)
{
_webhookService = webhookService;
}
[HttpGet]
public IActionResult VerifyWebhook([FromQuery] string hub_mode, [FromQuery] string hub_verify_token, [FromQuery] string hub_challenge)
{
var result = _webhookService.VerifyWebhook(hub_mode, hub_verify_token, hub_challenge);
if (result.IsValid)
return Ok(result.Challenge);
return Forbid();
}
[HttpPost]
public async Task<IActionResult> ProcessWebhook(CancellationToken cancellationToken)
{
using var reader = new StreamReader(Request.Body);
var body = await reader.ReadToEndAsync(cancellationToken);
await _webhookService.ProcessWebhookPayloadAsync(body, cancellationToken);
return Ok();
}
}
3. Default processor vs custom processor
- Default processor – The Lib registers
DefaultWhatsAppWebhookProcessor, which persists incoming messages, status updates, and history to WhatsAppMetaDbContext (same DB asWhatsappMetaService). No extra code needed; insert/update works when using the Lib in another project. - Custom processor – To use your own DB, SignalR, or external APIs, implement
IWhatsAppWebhookProcessorand register it (your registration overrides the default):
public interface IWhatsAppWebhookProcessor
{
Task ProcessIncomingMessagesAsync(WebhookPayloadContext context, IReadOnlyList<IncomingMessageDto> messages, CancellationToken cancellationToken = default);
Task ProcessStatusUpdatesAsync(WebhookPayloadContext context, IReadOnlyList<StatusUpdateDto> statuses, CancellationToken cancellationToken = default);
Task ProcessHistoryAsync(WebhookPayloadContext context, IReadOnlyList<HistoryMessageDto> history, CancellationToken cancellationToken = default);
}
// In Startup/Program:
builder.Services.AddScoped<IWhatsAppWebhookProcessor, MyWebhookProcessor>();
DTOs and context are in Lib.WhatsAppMeta.Webhook (WebhookPayloadContext, IncomingMessageDto, StatusUpdateDto, HistoryMessageDto). The Lib does not rethrow from ProcessWebhookPayloadAsync so you can always return 200 and avoid Meta retries.
4. Realtime / SignalR (optional)
When using the default webhook processor, you can push incoming messages and status updates to real-time clients (e.g. SignalR) by implementing IWhatsAppRealtimeNotifier and registering it. For a step-by-step implementation in another project (Hub, service, adapter, registration order, client connection), see REALTIME_SIGNALR_IMPLEMENTATION.md. The default processor then calls your notifier after persisting each incoming message and each status update (sent/failed), so other projects get the same ChatHub-style behaviour without a custom webhook processor.
- Implement
IWhatsAppRealtimeNotifier(e.g. an adapter that calls yourIHubContext<ChatHub>orIRealTimeService):
public class MySignalRNotifier : IWhatsAppRealtimeNotifier
{
private readonly IRealTimeService _realTimeService; // or IHubContext<ChatHub>
public MySignalRNotifier(IRealTimeService realTimeService) => _realTimeService = realTimeService;
public async Task NotifyAsync(WhatsAppRealtimeNotification n, CancellationToken ct)
{
await _realTimeService.SendMessageAsync(n.MessageId, n.ContextMessageId, n.EventName, n.ChatStatus,
n.FromPhoneNumber, n.ToRegisteredUserId, n.Message, n.ContactInfo ?? "", n.TotalRecords, n.ErrorMessage);
}
}
- Register your notifier before
AddWhatsAppMeta(so it is used instead of the default no-op):
builder.Services.AddWhatsAppRealtimeNotifier<MySignalRNotifier>();
builder.Services.AddWhatsAppMeta(builder.Configuration);
// Use the default processor (do not register a custom IWhatsAppWebhookProcessor) so the lib pushes via your notifier.
Event names and payload match the app’s ChatHub: ReceiveMessage for incoming messages, SendMessage for status updates. Use WhatsAppRealtimeStatus.Received (1) and WhatsAppRealtimeStatus.Send (2), or your app’s enum if values match.
CRM template sending (SendTemplateMessageCrm)
SendTemplateMessageCrm sends template messages using template metadata, optional media upload, and persist send-list entries. It needs:
- IWhatsAppCrmSendContext – Implemented by the Lib’s
WhatsAppCrmSendContext, which in turn needs the four providers below. - Four provider interfaces – You either use the Lib’s default implementations (when you have the same app infrastructure) or implement them yourself (e.g. when using the Lib as a NuGet package in another solution).
Provider interfaces (Lib.WhatsAppMeta.Models)
| Interface | Purpose |
|---|---|
IWhatsAppCrmClientIdProvider |
Returns WhatsApp/Meta client ID (e.g. from config). |
IWhatsAppImageUpload |
Uploads an image (e.g. base64) and returns UploadImageResultDto (e.g. path or URL). |
IBaseUrlProvider |
Returns your application’s base URL. |
IWhatsAppErrorParser |
Parses API error JSON and returns a user-facing message. |
WhatsAppCrmSendContext (Lib) uses these four plus WhatsAppMetaDbContext for template lookup and send-list persistence.
Scenario A: Same solution (project references Lib and App.Infrastructure)
If your project references Lib.WhatsAppMeta and the same solution’s App.Infrastructure (which defines IUploadImageService, IFacebookService, IFacebookErrorParserService), you can register the Lib’s default provider implementations and the Lib’s context:
using Lib.Config.FaceBookSetting;
using Lib.WhatsAppMeta.Extensions;
using Lib.WhatsAppMeta.Models;
using Lib.WhatsAppMeta.Services;
// 1) Bind Facebook settings (for WhatsAppCrmClientIdProvider)
builder.Services.Configure<FacebookSettings>(builder.Configuration.GetSection("Facebook"));
// 2) Add core WhatsApp Meta services and DbContext
builder.Services.AddWhatsAppMeta(builder.Configuration, "db", "crm");
builder.Services.UseWhatsAppMetaMigrations();
// 3) Register CRM providers and context (Lib implementations)
builder.Services.AddScoped<IWhatsAppCrmClientIdProvider, WhatsAppCrmClientIdProvider>();
builder.Services.AddScoped<IWhatsAppImageUpload, WhatsAppCrmImageUpload>();
builder.Services.AddScoped<IBaseUrlProvider, WhatsAppCrmBaseUrlProvider>();
builder.Services.AddScoped<IWhatsAppErrorParser, WhatsAppCrmErrorParser>();
builder.Services.AddScoped<IWhatsAppCrmSendContext, WhatsAppCrmSendContext>();
Note: Class names are WhatsAppCrmImageUpload, WhatsAppCrmBaseUrlProvider, etc. (with “Crm” in the name).
Scenario B: Using the Lib as a NuGet package (other solution)
The Lib’s default providers depend on App.Infrastructure. In a solution that does not reference that assembly, do not register the Lib’s provider classes. Implement the four interfaces in your project and register your implementations:
using Lib.WhatsAppMeta.Extensions;
using Lib.WhatsAppMeta.Models;
using Lib.WhatsAppMeta.Services;
builder.Services.AddWhatsAppMeta(builder.Configuration, "db", "crm");
builder.Services.UseWhatsAppMetaMigrations();
// Your own implementations (no App.Infrastructure)
builder.Services.AddScoped<IWhatsAppCrmClientIdProvider, MyClientIdProvider>();
builder.Services.AddScoped<IWhatsAppImageUpload, MyImageUpload>();
builder.Services.AddScoped<IBaseUrlProvider, MyBaseUrlProvider>();
builder.Services.AddScoped<IWhatsAppErrorParser, MyErrorParser>();
builder.Services.AddScoped<IWhatsAppCrmSendContext, WhatsAppCrmSendContext>();
Minimal example implementations (replace with your real config and services):
using Lib.WhatsAppMeta.Models;
using Microsoft.Extensions.Options;
public class MyClientIdProvider : IWhatsAppCrmClientIdProvider
{
private readonly FacebookSettings _settings;
public MyClientIdProvider(IOptions<FacebookSettings> opts) => _settings = opts?.Value ?? throw new ArgumentNullException(nameof(opts));
public string ClientId => _settings?.ClientId ?? "";
}
public class MyImageUpload : IWhatsAppImageUpload
{
public Task<UploadImageResultDto> UploadImageAsync(string base64Path, string folder, CancellationToken ct = default)
{
// Use your app’s upload service and return path/link
return Task.FromResult(new UploadImageResultDto { ImagePath = null });
}
}
public class MyBaseUrlProvider : IBaseUrlProvider
{
private readonly IConfiguration _config;
public MyBaseUrlProvider(IConfiguration config) => _config = config;
public string GetBaseUrl() => _config["BaseUrl"] ?? "https://yoursite.com";
}
public class MyErrorParser : IWhatsAppErrorParser
{
public string ParseErrorMessage(string apiError)
{
if (string.IsNullOrWhiteSpace(apiError)) return "An error occurred.";
try
{
var doc = System.Text.Json.JsonDocument.Parse(apiError);
if (doc.RootElement.TryGetProperty("error", out var err) && err.TryGetProperty("message", out var msg))
return msg.GetString() ?? apiError;
}
catch { }
return apiError;
}
}
Creating message templates
- Without media: use
CreateMessageTemplate(CreateMessageTemplateRequest, wabaId, accessToken, cancellationToken). - With media (image/video/document): use
CreateMessageTemplateWithMedia(object commandRequest, wabaId, accessToken, clientId, phoneNumberId, ICreateTemplateContext?, MessageTemplateSaveOptions?, cancellationToken). The Lib validates base64 size, uploads media, then creates the template. Optionally passICreateTemplateContextandMessageTemplateSaveOptionsto persist the template in your DB.
Optional persistence after create
Implement ICreateTemplateContext and pass it (and MessageTemplateSaveOptions) when calling CreateMessageTemplateWithMedia:
public interface ICreateTemplateContext
{
Task SaveMessageTemplateAsync(MessageTemplateSaveDto dto, CancellationToken cancellationToken = default);
}
Register your implementation and pass it from your app layer when invoking CreateMessageTemplateWithMedia.
Entities and DbContext
DbContext: WhatsAppMetaDbContext (from Lib.WhatsAppMeta.Data).
Entities (Lib.WhatsAppMeta.Entities):
WAUserCredential– WhatsApp user credentialsWAUserCredentialUsersMappingWAWebhookMsgStatus– Webhook message/status/history (default processor persists here)SendWAMessageList– Sent message list (used by CRM send and status updates)MetaChargeListMessageTemplate– Template metadata (used by CRM send)BroadcastCampaign– Broadcast campaignsBroadcastRecipient– Broadcast recipients
You can inject WhatsAppMetaDbContext for direct DB access when needed.
Data insert and webhook in any project
When you use the Lib as a package in another project, the same DbContext and patterns apply so inserts and updates work without app-specific code.
Audit fields (CreatedBy, UpdatedBy, DeletedBy)
WhatsAppMetaDbContext.SaveChangesAsync sets these when an IWhatsAppMetaUserIdProvider is registered. If you do not register one, the fields remain null and inserts still work. To set them:
builder.Services.AddScoped<IWhatsAppMetaUserIdProvider, MyUserIdProvider>();
Webhook persistence
See Webhook (Meta callback). The default processor persists to WhatsAppMetaDbContext; register your own IWhatsAppWebhookProcessor to override (e.g. your DB or SignalR).
Database setup and migrations
Automatic (recommended)
Call after AddWhatsAppMeta:
builder.Services.UseWhatsAppMetaMigrations();
This runs the Lib’s embedded SQL installation (tables, schema) at startup. Ensure the connection string is valid and the app has DB permissions.
Manual
If you use EF Core migrations in the Lib project:
dotnet ef migrations add InitialCreate --context WhatsAppMetaDbContext --project Lib.WhatsAppMeta
dotnet ef database update --context WhatsAppMetaDbContext --project Lib.WhatsAppMeta
Stored procedures (refresh SQL in another project)
The Lib uses three stored procedures: sp_GetAllChatByNumber, sp_GetAllContactList, sp_GetAllBroadcastList.
Your host project’s “refresh SQL” (or programmability step) usually reads from its own output folder (e.g. Programmability/StoredProcedures/*.sql). When you use Lib.WhatsAppMeta as a package, those scripts are not in your project by default.
Option 1: Extract SQL files to your project (recommended if your refresh reads from disk)
Extract the SQL files to your Programmability/StoredProcedures/ folder so your existing refresh SQL step picks them up:
using Lib.WhatsAppMeta.Data;
// One-time setup (e.g. in a migration script or startup):
var targetDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Programmability", "StoredProcedures");
WhatsAppMetaStoredProcedures.ExtractStoredProceduresToDirectory(targetDir);
After extraction, your refresh SQL step will find them in Programmability/StoredProcedures/ and include them automatically.
Option 2: Execute programmatically (if you want to run them directly)
Call WhatsAppMetaStoredProcedures.ExecuteStoredProcedures(yourDbContext) after your existing programmability step:
using Lib.WhatsAppMeta.Data;
using Microsoft.EntityFrameworkCore;
// In your DbHelper or refresh handler, after your existing AddProgrammabilitySQLFiles(dbContext):
WhatsAppMetaStoredProcedures.ExecuteStoredProcedures(dbContext);
Option 3: Get scripts and handle yourself
Enumerate scripts and write/execute them as needed:
foreach (var (fileName, content) in WhatsAppMetaStoredProcedures.GetStoredProcedureScripts())
{
// Write to disk, execute, etc.
}
Note: The SQL files are also included as ContentFiles in the NuGet package (under content/Lib.WhatsAppMeta.Sql/StoredProcedures/), but they won't automatically appear in your project structure. Use Option 1 to extract them to your desired location.
📖 For detailed SQL files usage guide, see SQL_FILES_GUIDE.md
SQL Files Guide
Quick reference for SQL files location and usage:
- Files location:
Sql/StoredProcedures/in source,content/Lib.WhatsAppMeta.Sql/StoredProcedures/in package - Extract to project:
WhatsAppMetaStoredProcedures.ExtractStoredProceduresToDirectory("Programmability/StoredProcedures") - Execute directly:
WhatsAppMetaStoredProcedures.ExecuteStoredProcedures(dbContext)
See SQL_FILES_GUIDE.md for complete documentation with examples and troubleshooting.
Requirements
- .NET 7.0 or later
- SQL Server (for DbContext and CRM persistence)
- WhatsApp Business API (Meta) credentials and configuration
Troubleshooting
| Error or symptom | What to do |
|---|---|
| Unable to resolve service for type 'WhatsappMetaService' | Inject IWhatsappMetaService, not the concrete WhatsappMetaService type. |
| Could not load type 'App.Infrastructure...' | You are registering the Lib’s default CRM providers in a project that does not reference App.Infrastructure. Use Scenario B: implement the four provider interfaces in your project and register those implementations. |
| 'WhatsAppImageUpload' could not be found | The implementation class name is WhatsAppCrmImageUpload (with “Crm”). Use that, or your own implementation of IWhatsAppImageUpload. |
| Package downgrade (Microsoft.Extensions.DependencyInjection.Abstractions 8.0.0 → 7.0.0) | The Lib references 8.0.0. If your app or another package forces 7.x, align versions (e.g. upgrade the app to 8.0.0 or use a single shared version). |
| DbContext not registered / migrations not running | Ensure you pass a non-null, non-empty connection string to AddWhatsAppMeta (via config key or direct string). Call UseWhatsAppMetaMigrations() only when the connection string is available. |
| Webhook GET returns 403 / verification fails | Ensure AddWhatsAppMetaWebhook("YourToken") uses the same token as in the Meta App Dashboard (Webhook → Verify token). |
| Webhook POST succeeds but no data in DB | Ensure WAUserCredentials has a row for the webhook's WABA ID and the credential is not soft-deleted. Default processor looks up by context.WabaId. If you use a custom processor, ensure it is registered (e.g. AddScoped<IWhatsAppWebhookProcessor, YourProcessor>()). |
| Method not found: GetCurrentUserId | The Lib uses IWhatsAppMetaUserIdProvider (optional). If you see this from another assembly, do not inject the Lib's HttpContextUserIdProviderAdapter in that project, or implement your own IWhatsAppMetaUserIdProvider without depending on the missing method. |
License
MIT. For issues or contributions, see the GitHub repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net7.0
- App.Infrastructure (>= 1.0.0)
- Lib.Config (>= 1.0.0)
- Lib.Core (>= 1.0.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 7.0.11)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.48 | 115 | 3/16/2026 |
| 1.0.47 | 90 | 3/14/2026 |
| 1.0.46 | 78 | 3/14/2026 |
| 1.0.45 | 81 | 3/14/2026 |
| 1.0.44 | 91 | 3/13/2026 |
| 1.0.43 | 84 | 3/13/2026 |
| 1.0.42 | 95 | 3/5/2026 |
| 1.0.41 | 94 | 3/4/2026 |
| 1.0.40 | 81 | 3/4/2026 |
| 1.0.39 | 98 | 3/3/2026 |
| 1.0.38 | 81 | 3/3/2026 |
| 1.0.37 | 81 | 3/3/2026 |
| 1.0.36 | 79 | 3/3/2026 |
| 1.0.35 | 75 | 3/3/2026 |
| 1.0.34 | 79 | 3/3/2026 |
| 1.0.33 | 81 | 3/3/2026 |
| 1.0.32 | 82 | 3/3/2026 |
| 1.0.31 | 84 | 3/3/2026 |
| 1.0.30 | 95 | 3/2/2026 |
| 1.0.29 | 98 | 3/2/2026 |