# Veracity Pay – Swish Commerce API (Swish Handel)

Base URL `https://pay.veracity.se/swish/<secret key>` in place of https://mss.cpc.getswish.net (the key in the base URL stands in for the client certificate; every Swish SDK lets you set the base URL). Paths and bodies are Swish's own: `/swish-cpcapi/api/v2/paymentrequests/{instructionUUID}`, `/swish-cpcapi/api/v1/paymentrequests/{id}`, `/swish-cpcapi/api/v2/refunds/{instructionUUID}`, `/recurring/merchant/v1/…`, `/qrg-swish/api/v1/commerce`.

## 1. Environment
```
SWISH_BASE_URL=https://pay.veracity.se/swish/vp_sk_test_…   # from the registration e-mail
SWISH_PAYEE_ALIAS=123…                       # your Veracity Swish number (payeeAlias)
```

## 2. Create a payment request
```http
PUT https://pay.veracity.se/swish/vp_sk_test_…/swish-cpcapi/api/v2/paymentrequests/{32 upper-case hex}
Content-Type: application/json

{"payeePaymentReference":"0123456789","callbackUrl":"https://your-app/api/swish/callback","payerAlias":"46712345678","payeeAlias":"<SWISH_PAYEE_ALIAS>","amount":"100.00","currency":"SEK","message":"Order 1001"}
```
201 with `Location`. Without `payerAlias` (m-commerce) the response also has `PaymentRequestToken`.

## 3. The payer approves
- e-commerce (payerAlias): the payer opens https://pay.veracity.se/swish/app, enters the number and approves with a code sent to their e-mail.
- m-commerce: send the payer to `https://pay.veracity.se/swish/paymentrequest?token=<PaymentRequestToken>&callbackurl=<your return URL>` (instead of `swish://paymentrequest?…`).
- Without a browser: `POST https://pay.veracity.se/v1/test_helpers/checkout/sessions/{instructionUUID}/complete` with `outcome` (MCP tool `complete_checkout`).
- MSS magic messages work: `message` equal to an early code (FF08, RP03, BE18, RP01, PA02, AM06, AM02, AM03, RP02, RP06, ACMT03, ACMT01, ACMT07, UNKW) gives 422 with that code; a late code (RF07, BANKIDCL, FF10, TM01, DS24) gives status ERROR with that code once the payer acts.

## 4. Callback and status
Swish POSTs the payment request object (PAID, DECLINED, ERROR or CANCELLED) to callbackUrl, with your `callbackIdentifier` as a header. Callbacks are not signed: re-read `GET …/v1/paymentrequests/{id}` before acting. Cancel with `PATCH` and `[{"op":"replace","path":"/status","value":"cancelled"}]` (Content-Type application/json-patch+json).

## 5. Refunds and recurring payments
- `PUT …/v2/refunds/{instructionUUID}` with originalPaymentReference (the payment's paymentReference), payerAlias (your Swish number), amount, currency, callbackUrl. Callbacks: DEBITED, then PAID.
- Recurring: `POST /recurring/merchant/v1/consents/{consentId}` (payer alias) → the payer signs in https://pay.veracity.se/swish/app; then `POST /recurring/merchant/v1/payments/single/{paymentId}` charges without the payer. `SIMULATE_ERROR_CODE` as a header simulates errors, like MSS.

## Going live and deviations from the original

Original documentation: [Swish Payment Request API v2](https://developer.swish.nu/api/payment-request/v2), [Swish Refunds API v2](https://developer.swish.nu/api/refunds/v2), [Swish Recurring Payments API v1](https://developer.swish.nu/api/recurring-payments/v1), [Swish QR codes](https://developer.swish.nu/api/qr-codes/v1), [Merchant Swish Simulator](https://developer.swish.nu/api/mss/v1).

To go live, change only the host and the keys: MSS (simulator): `https://mss.cpc.getswish.net`; Production: `https://cpc.getswish.net`. Remove the key from the base URL, add your Swish certificate (.p12) and replace payeeAlias with your real Swish number.

Deviations in Veracity Pay:
- No client certificate (mTLS): the account is identified by the key in the base URL ({host}/swish/vp_sk_test_…), by Authorization: Bearer or by payeeAlias.
- The payer approves in an emulated Swish app (/swish/app) with an e-mailed code; MSS instead marks everything paid after 4 seconds.
- m-commerce: open {host}/swish/paymentrequest?token=…&callbackurl=… instead of swish://paymentrequest?…; consents: {host}/swish/r?sw=…&ret=… instead of app.swish.nu.
- The QR code holds the link to the emulated app, not D + token, and JPEG is delivered as PNG.
- Callbacks may use http outside production. Payouts are missing.
