wayl_pay 0.2.4 copy "wayl_pay: ^0.2.4" to clipboard
wayl_pay: ^0.2.4 copied to clipboard

Typed Dart client for the Wayl merchant API.

wayl_pay #

wayl_pay is a typed Dart client for the Wayl merchant API.

It wraps the public v1 merchant endpoints exposed at https://api.thewayl.com and handles:

  • API key authentication through X-WAYL-AUTHENTICATION
  • Environment switching between production and staging
  • Payment link creation in both live and test modes
  • Typed request and response models
  • Pagination and status filters
  • Consistent API error handling with validation details
  • A raw JSON request escape hatch for forward compatibility

Covered routes #

The package currently covers all public merchant routes documented in the Wayl OpenAPI document:

  • GET /api/v1/verify-auth-key
  • GET /api/v1/channels
  • POST /api/v1/links
  • GET /api/v1/links
  • GET /api/v1/links/{referenceId}
  • POST /api/v1/links/{referenceId}/invalidate
  • POST /api/v1/links/{referenceId}/invalidate-if-pending
  • POST /api/v1/links/batch
  • GET /api/v1/products
  • GET /api/v1/products/{productId}
  • GET /api/v1/subscriptions
  • GET /api/v1/subscriptions/{productId}
  • GET /api/v1/subscribers
  • POST /api/v1/refunds
  • GET /api/v1/refunds
  • GET /api/v1/refunds/{refundId}
  • DELETE /api/v1/refunds/{refundId}/cancel

Installation #

Add the package to your Dart or Flutter application:

dependencies:
	wayl_pay: ^0.2.4

Webhook Verification #

Wayl sends payment status updates to your webhook URL. To verify the authenticity of these webhooks:

  1. Set a webhookSecret when creating a payment link.
  2. When your server receives a webhook, use the WaylWebhookVerifier utility:
import 'package:wayl_pay/wayl_pay.dart';

final isValid = WaylWebhookVerifier.verify(
	payload: requestBody, // raw POST body
	signature: request.headers['x-wayl-signature'],
	secret: 'your-webhook-secret',
);

if (!isValid) {
	// Reject the webhook
}

This uses HMAC-SHA256 to verify the signature. Always check the signature before processing the webhook payload.


How it works #

wayl_pay provides a strongly-typed, modern Dart interface for the Wayl merchant API. It is designed for both Dart and Flutter projects, and abstracts away raw HTTP, authentication, and error handling.

Architecture #

  • WaylPayClient: The main entry point. Configure with your API key and environment (production or staging).
  • API Groups: Access endpoints via logical groups: client.links, client.products, client.subscriptions, client.refunds, etc.
  • Typed Models: All requests and responses use Dart classes, so you get autocompletion and type safety.
  • Error Handling: All errors throw WaylApiException, which includes HTTP status, message, and validation errors (if any).
  • Extensibility: For new or undocumented endpoints, use client.requestJson to send custom requests and receive raw JSON.

Request Flow #

  1. Instantiate WaylPayClient with your API key:
    final client = WaylPayClient(apiKey: 'YOUR_KEY');
    
  2. Call an endpoint (e.g., create a payment link):
    final response = await client.links.create(CreateLinkRequest(...));
    print(response.data.url);
    
  3. Handle errors with try/catch:
    try {
    	 await client.refunds.create(...);
    } on WaylApiException catch (e) {
    	 print(e.message);
    }
    
  4. Close the client when done:
    client.close();
    

Features #

  • Authentication: Uses the X-WAYL-AUTHENTICATION header automatically.
  • Environment Switching: Use WaylEnvironment.production or WaylEnvironment.staging.
  • Pagination & Filtering: Query objects like ListLinksQuery and ListProductsQuery make pagination and filtering easy.
  • Validation Errors: If the API returns validation errors, they are available in WaylApiException.errors.
  • Testability: All HTTP is injectable for mocking in tests.
final links = await client.links.list(
	const ListLinksQuery(statuses: {LinkStatus.pending}),
);
for (final link in links.data) {
	print(link.referenceId);
}

Quick start #

import 'package:wayl_pay/wayl_pay.dart';

Future<void> main() async {
	final client = WaylPayClient(
		apiKey: 'YOUR_WAYL_API_KEY',
		environment: WaylEnvironment.production,
	);

	final auth = await client.authentication.verifyKey();
	print(auth.message);

	final links = await client.links.list(
		const ListLinksQuery(take: 20, statuses: {LinkStatus.pending}),
	);

	for (final link in links.data) {
		print('${link.referenceId}: ${link.status?.value ?? 'unknown'}');
	}

	client.close();
}
final response = await client.links.create(
	CreateLinkRequest(
		env: LinkEnvironment.live,
		referenceId: 'invoice-2026-0001',
		total: 25000,
		customParameter: 'customer-42',
		lineItems: const [
			LinkLineItem(
				label: 'Premium Plan',
				amount: 25000,
				type: LinkLineItemType.increase,
			),
		],
		webhookUrl: Uri.parse('https://example.com/webhooks/wayl'),
		webhookSecret: 'replace-with-a-long-secret',
		redirectionUrl: Uri.parse('https://example.com/payment-complete'),
	),
);

print(response.data.url);

Use LinkEnvironment.test when you want Wayl to create a test payment link instead of a live one:

final response = await client.links.create(
	CreateLinkRequest(
		env: LinkEnvironment.test,
		referenceId: 'invoice-test-0001',
		total: 25000,
		webhookUrl: Uri.parse('https://example.com/webhooks/wayl'),
		webhookSecret: 'replace-with-a-long-secret',
		redirectionUrl: Uri.parse('https://example.com/payment-complete'),
		lineItems: const [
			LinkLineItem(
				label: 'Test payment',
				amount: 25000,
				type: LinkLineItemType.increase,
			),
		],
	),
);

print(response.data.url);

This sends env: "test" to the Wayl API, which is useful for integration testing before switching to LinkEnvironment.live. Wayl also requires webhookUrl, webhookSecret, and redirectionUrl when creating a link.

Error handling #

try {
	await client.refunds.create(
		const CreateRefundRequest(
			referenceId: 'invoice-2026-0001',
			reason: 'A detailed refund explanation with at least one hundred characters so it satisfies the API validation requirements.',
			amount: 1000,
		),
	);
} on WaylApiException catch (error) {
	print(error.message);
	for (final validationError in error.errors) {
		print('${validationError.path.join('.')}: ${validationError.message}');
	}
}

Notes #

  • All amounts are in IQD.
  • The API uses your merchant key in the X-WAYL-AUTHENTICATION header.
  • Use WaylEnvironment.staging for test integrations if you have staging credentials.
  • Use LinkEnvironment.test when creating links for payment-flow testing.
  • WaylPayClient.requestJson is available for new endpoints that may be added before this package is updated.
1
likes
140
points
10
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Typed Dart client for the Wayl merchant API.

Homepage

Topics

#payments #api-client #commerce #wayl #iraq

License

MIT (license)

Dependencies

crypto, http

More

Packages that depend on wayl_pay