sextanet/laravel-oneclick
Sextanet's Laravel OneClick package brings one-click convenience to Laravel apps, letting you trigger common setup and action flows from a single call. Lightweight, easy to configure, and designed to fit naturally into existing Laravel projects.
First, a correction worth making up front: the package summary in some indexes describes magic-link auth or a
shared-hosting web installer. That is wrong. sextanet/laravel-oneclick wraps Transbank Oneclick (Webpay Oneclick),
the Chilean card-on-file payment gateway: you inscribe a card once, get a tbk_user token back, and then charge that
token repeatedly without the cardholder present. Plan accordingly — this is a payments dependency, not an auth one.
composer require sextanet/laravel-oneclickphp artisan vendor:publish --tag=oneclick-config (check the provider for the exact tag)..env:
ONECLICK_ENVIRONMENT=integration
ONECLICK_COMMERCE_CODE=597055555541
ONECLICK_API_KEY=<integration secret>
The integration commerce code and secret are Transbank's public sandbox values — never ship them to production.config/oneclick.php for the credential/environment wiring, then src/ for the facade and the
single client class behind it. The README is thin and there are no real docs, so the source is the documentation.First use case to build: the inscription round-trip. A logged-in user clicks "Save card", you redirect them to
Webpay, they return to a callback route, and you persist the resulting tbk_user on their account. Once that works,
everything else (charging, deleting) is a short hop.
Inscription (two routes, one controller). Route A builds the request and redirects out; route B receives the POST
back from Transbank with a TBK_TOKEN in the body.
// POST /cards/inscribe
public function start(Request $request)
{
$result = Oneclick::startInscription(
username: (string) $request->user()->id,
email: $request->user()->email,
responseUrl: route('cards.callback'),
);
return redirect()->away($result->url);
}
// POST /cards/callback (outside `auth`, see gotchas)
public function callback(Request $request)
{
$result = Oneclick::finishInscription($request->input('TBK_TOKEN'));
$request->user()->cards()->create([
'tbk_user' => $result->tbkUser,
'card_type' => $result->cardType,
'last4' => $result->last4,
]);
return redirect()->route('billing.index');
}
Persist the token properly. tbk_user is a bearer credential — whoever holds it can charge the card. Cast it
encrypted on the model, exclude it from $fillable mass-assignment where you can, and keep it out of
toArray()/queue payloads.
Charging. parentBuyOrder identifies the basket, childBuyOrder the individual line; both must be unique across
your commerce. Amounts are integers.
$charge = Oneclick::authorize(
username: (string) $order->user_id,
tbkUser: $card->tbk_user,
parentBuyOrder: $order->number, // ≤ 26 chars
childBuyOrder: "{$order->number}-1",
amount: (int) $order->total, // CLP, no decimals
);
if ($charge->responseCode !== 0) {
throw new PaymentDeclined($charge->responseCode);
}
Wrap it, don't sprinkle it. Put a CardCharger / InscriptionService around the facade and dispatch a domain event
(CardInscribed, PaymentCharged) for each result. Auditing is the whole reason to have an events layer here — when
Transbank disputes a charge you want your own record of the buy orders and response codes.
Integration tips that save time:
ONECLICK_ENVIRONMENT=integration with Transbank's published sandbox cards; production credentials will
not work there and vice-versa.Http::fake() the Transbank endpoints for unit tests, but keep at least one manual pass through the real sandbox —
the redirect flow is where things break, not your JSON parsing.php artisan config:cache after every env change during setup; stale config is the #1 "why is it hitting production"
cause.9990.0 will either fail validation or charge the wrong value.responseCode === 0 is approved. Everything else is a failure with a distinct meaning; log the code rather
than a boolean.auth middleware (Transbank POSTs from outside), but you still
need to know which user is inscribing. Stash the user id in the session before redirecting, or use a signed URL as
the responseUrl — Laravel's URL::temporarySignedRoute fits neatly here.finishInscription on an already-consumed token throws. Wrap both callback
handlers in try/catch and render a friendly "card wasn't saved, try again" instead of a 500.TBK_TOKEN, tbk_user, or the API key. Log the buy order, amount, and response code —
that's enough to debug and safe to keep.^2.1 is safe. But
the package is young and single-maintainer — read the diff before bumping a minor, and keep your own thin adapter
layer so a breaking change is a one-file fix.How can I help you explore Laravel packages today?