View as Markdown

llms.txt

This guide isn't available right now

This instance couldn't load its guide catalog. The guide returns as soon as the catalog is readable again.

Back to the guides

No such guide

This instance publishes no guide under that address. It may have been renamed, or it may belong to a feature this installation hasn't enabled.

Back to the guides

That guide is part of the product documentation

This guide is written for someone operating WinkPG through its screens rather than integrating against it, so it lives in the application's own help section instead of here. Sign in to WinkPG and open Help to read it.

Back to the guides

Guides Quickstart

Quickstart: Embedded payments SDK

Mount the WinkPG payment form inside your own checkout page with the browser loader.

The payer stays on your checkout page and the card fields are rendered inside a frame WinkPG serves. Your page keeps its own layout and flow, and neither your page nor your server ever touches a card number.

This is the redirect flow's sibling: the same page and the same session, mounted in place instead of navigated to. Set up the hosted page first, then come back here.

You need a hosted page id, an API key, and the origin your checkout is served from.

1. Authorize your origin to embed

Two settings have to line up, and a mismatch is the single most common reason an embed shows nothing.

Add your checkout's domain to the hosted page's allowed embedding domains in the portal. Wildcards such as *.example.com work; raw IP addresses, localhost, and entries with no top-level domain are rejected.

Then name the exact origin on every session you create. If the origin is omitted the session still works for a redirect, but the message channel the loader depends on stays closed, and your page receives nothing.

2. Create the session on your server

curl -X POST "https://your-gateway-host/api/hostedpaymentpages/sessions" \
  -H "api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "hostedPageId": "{hostedPageId}",
    "label": "Order 1042",
    "parentOrigin": "https://checkout.example.com",
    "amountMode": "Locked",
    "prefilledFields": { "base_amount": "10.00" },
    "expirySeconds": 900
  }'

The response carries hppUrl, the absolute address the frame will point at, already resolved against the payment host. Hand that value back to your page. There's no second call to make for it:

{
  "sessionId": "3f1c...",
  "shortToken": "aB3kX9mZqR7T",
  "hppUrl": "https://pay.your-environment.example/pay/s/aB3kX9mZqR7T",
  "expiresAt": "2026-01-01T18:30:00Z",
  "label": "Order 1042"
}

Keep the call on the server. The API key must never reach the browser: a key in page source is a credential anyone who views source can use.

3. Add the script

<script src="https://pay.your-environment.example/sdk/v1/pay.js"></script>

The loader is a few hundred bytes. It resolves the release your payment host is actually serving, injects the payment code with its integrity attribute already applied, and assigns a window global.

The name of that global is a per-deployment value, so no single name this page could print would be right everywhere. Your administrator reads it off the branding settings. The examples below call it PaySdk:

var PaySdk = window.YourConfiguredGlobalName;

https://pay.your-environment.example is a placeholder and doesn't resolve. Your administrator has the payment host for your environment.

4. Mount the form

<div id="checkout"></div>

<script>
  var payment = PaySdk.mount('#checkout', {
    sessionUrl: SESSION_URL_FROM_YOUR_SERVER,

    onComplete: function (outcome) {
      window.location = '/order/confirmed?ref=' + encodeURIComponent(outcome.transactionId);
    },
    onFailed: function (outcome) {
      showMessage(outcome.responseMessage || outcome.reason || 'That payment was not approved.');
    },
    onCancelled: function () {
      window.location = '/cart';
    },
    onSessionInvalid: function () {
      showMessage('This checkout is no longer usable. Start again to get a fresh one.');
    }
  });
</script>

The container is an element or a CSS selector. A selector matching nothing throws straight away, on the page that set it up, rather than failing in front of a payer with no explanation.

In a single-page application, call payment.destroy() when the view unmounts. Leaving the frame and its message listener attached across a route change is the reliable way to end up with two mounts competing for one page.

5. Confirm from the webhook, not from the callback

onComplete is what you show the person looking at the screen. The webhook is the record. A browser that loses its connection between the approval and the callback leaves your page with nothing and your server with a real payment, so the reconciliation path has to be the delivery your server receives.

Next steps

Reconnecting to the server

Could not reconnect

This session has ended

Attempt 1

Your work on this page is still here. Retrying keeps it; reloading starts the page again.

The server no longer holds this page's state, so it has to be loaded again.