Guides → Setup
Salesforce B2C Commerce
Salesforce B2C Commerce (SFRA) setup
Install the Open Border cartridge pair on a Salesforce B2C Commerce SFRA storefront, import and configure its Business Manager metadata, take a sandbox card payment, and understand what this pilot deliberately leaves out.
Step 1
Before you start
| Cartridge version | Compatibility mode | SFRA (app_storefront_base) |
|---|---|---|
| 0.1.0 | 22.7 (target baseline) | 6.3+ |
The cartridge code is written to the ES5.1 Rhino subset throughout. The tested matrix will be confirmed against a sandbox before any merchant handoff, which is tracked with the sample-storefront deployment.
- An Open Border merchant account whose KYB review has been approved.
- A B2C Commerce sandbox with Business Manager administrator access.
- The versioned release artifact:
openborder-salesforce-<version>.zipplus its.zip.sha256checksum and.manifest.json. Pin the released artifact — never copy cartridge source into a storefront. - A basket currency of USD, GBP, EUR, CAD, or AUD. The charge currency selects the Open Border legal entity that acquires the payment.
- A way to deploy a code version:
sfcc-ci code:deploy, the Commerce Cloud VS Code extension, or WebDAV.
Step 2
Get your test keys
-
1
Copy the secret key
From the Open Border dashboard in test mode, take the
sk_test_key. It goes into the Business Manager service credential — the cartridge derives the rail from the key prefix and fails closed if a live key is pointed at anything but the pinned production origin, or if the service URL is not HTTPS. -
2
Generate an installation UUID
Run
uuidgen, or use any UUID v4 generator, and keep the value. It scopes every idempotency key for this site, so it is set once and never changed afterwards. Changing it later would make in-flight retries look like new operations. -
3
Leave the webhook secret for later
The
whsec_signing secret is issued once, when you register the webhook endpoint. Do that after the metadata import, so you can build the endpoint URL from your real site id.
Step 3
Install
Verify the artifact checksum first. An archive whose checksum does not match its published .sha256 must not be installed.
sha256sum --check openborder-salesforce-<version>.zip.sha256
unzip openborder-salesforce-<version>.zip
The archive contains two deployables, and they install through different Business Manager paths: cartridges/ is uploaded as a code version, and metadata/site_import/ is zipped and imported as a site import.
| Piece | Purpose |
|---|---|
| cartridges/int_openborder | Platform-agnostic core: the API client, exact minor-unit money mapping, single-flight payment attempts, idempotency keys, monotonic status projection, webhook verification and deduplication, and the reconcile and purge job steps. |
| cartridges/int_openborder_sfra | Storefront glue: payment processor hooks, the place-order extension with the authentication pause and confirm flow, the notify, confirm, and checkout-config controllers, and the browser tokenisation assets. |
| metadata/site_import | The Business Manager import bundle: object extensions, the service definition, the jobs, and the payment method and processor. |
-
1
Upload both cartridges as a new code version
Create a new code version — for example
openborder_<version>— and upload both cartridge folders into it. - 2 Activate the code version Administration → Site Development → Code Deployment, then activate the new version. Rollback later is simply re-activating the previous version.
-
3
Prepend the cartridge path
Administration → Sites → Manage Sites → your site → Settings, then put both cartridges at the front of the path. They must sit before
app_storefront_baseand before any other storefront cartridge that overrides checkout services, or the payment hooks never run.
int_openborder_sfra:int_openborder:app_storefront_base
Step 4
Configure
-
1
Prepare the metadata bundle
Replace the
SITE_ID_PLACEHOLDERfolder name — and thesite-idinsidejobs.xml— with your real site id. The bundle ships with a placeholder and never a real site id or any credential. -
2
Import it
Zip
site_import/and upload it through Administration → Site Development → Site Import & Export, then run the import. -
3
If the import rejects the payment processor
Some instances refuse the
payment-processorelement. Create it manually first — Administration → Operations → Payment Processors → New, with idOPENBORDER_CREDIT— then re-import.
The import creates the Open Border site preferences group, custom attributes on Order, OrderPaymentInstrument, and Product, the OpenBorderAttempt and OpenBorderWebhookDelivery custom object types, the openborder.http.api service with its profile and credential, the OPENBORDER_CREDIT payment processor and method, and two disabled jobs.
| Field | What it does | Set it to |
|---|---|---|
openborder.http.api.credentials — URL |
The API origin for the selected rail. Administration → Operations → Services → Credentials. | https://api-demo.openborderpayments.com for test, https://api.openborderpayments.com for live. Must be HTTPS — the cartridge fails closed otherwise. |
openborder.http.api.credentials — Password |
The Open Border secret key. The rail is derived from its prefix, and a live key against a non-production origin fails closed. | The sk_test_ or sk_live_ key matching the URL above. |
obInstallationId |
Scopes every idempotency key for this site. Merchant Tools → Site Preferences → Custom Preferences → Open Border. | A UUID v4, generated once and never changed afterwards. Changing it breaks retry identity for anything in flight. |
obWebhookSecret |
Verifies the signature on each inbound callback. A password-type preference. | The whsec_ value from the matching rail’s endpoint. Set it after the next step. |
obHsCode |
Per-product tariff classification, set on the product under Merchant Tools → Products → your product → Open Border group. | Required on every sellable product. Checkout fails closed for any basket line without one. |
Finally enable the two jobs under Administration → Operations → Jobs. Both are imported disabled, and leaving them that way is the most common cause of stuck orders on this platform.
OpenBorder-ReconcileAttempts— enable the hourly trigger. This is the repair loop for delayed callbacks, abandoned authentication challenges, and unknown provider outcomes. Without it, an order that pauses for authentication can stay unplaced with no path to recovery.OpenBorder-PurgeDeliveryLog— enable the daily trigger. It retains webhook deduplication records; custom object quotas are finite, so this is not optional maintenance.
Step 5
Connect webhooks
Register a webhook endpoint in the Open Border dashboard for the matching mode, pointing at the cartridge’s notify controller on your instance. Subscribe it to at least the payment-intent and refund event types, then copy its one-time whsec_ signing secret into the obWebhookSecret site preference.
https://<instance-host>/on/demandware.store/Sites-<SiteId>-Site/default/OpenBorder-Notify
- Deliveries are verified with HMAC-SHA256, a 300-second replay window, rotation awareness, and a fixed-time comparison, so the server clock must be synchronised.
- Deliveries are deduplicated by delivery id. A crashed worker’s unprocessed claim becomes reclaimable after 300 seconds, and a failed reconcile releases the claim so the retry reprocesses.
- A callback is a prompt, not the truth. The cartridge reads authoritative payment status before applying any forward transition, so duplicate and out-of-order deliveries are safe.
Step 6
Run a test payment
Run all four checks on the storefront in test mode. The authentication and decline paths are where a cartridge-path or job misconfiguration actually surfaces, so a single success proves very little.
-
1
Successful payment
Add a product carrying an
obHsCodeand check out with card4242 4242 4242 4242. The order is placed, payment status is Paid, andOrder.custom.obStatusreadssucceededorcaptured. -
2
Authentication challenge
Use card
4000 0027 6000 3184. The challenge appears; completing it lands on the order confirmation. Abandon it instead and the order must stay unplaced — a later checkout retry then supersedes the stale attempt rather than charging twice. -
3
Decline
Use card
4000 0000 0000 0002. The shopper sees a customer-safe error, the order is failed, and the basket reopens. - 4 Callback delivery and replay Send a test event from the dashboard and confirm a success in the delivery log. Replay the same delivery and confirm it also succeeds as a duplicate, without reprocessing.
-
5
Check the logs are clean
Administration → Site Development → Development Setup → log files, prefix
openborder. Confirm no secret key, webhook secret, client secret, card number, or email address appears. Every log line passes through a redacting logger, so anything that leaks is a bug worth reporting.
Step 7
Go live
-
1
Swap the service credential to live
Change both the URL and the key together, to the pinned production origin and an
sk_live_key. A live key against any other origin fails closed, which is the intended behaviour. -
2
Register the live webhook endpoint
A separate endpoint with its own
whsec_secret, and updateobWebhookSecretto match. Never carry a sandbox secret across. - 3 Leave obInstallationId alone It is set once for the site and scopes every idempotency key. Do not regenerate it as part of going live.
- 4 Confirm both jobs are enabled and running Hourly reconcile and daily purge. Check the job history, not just the enabled flag.
- 5 Confirm the notify path is reachable If production carries any access protection, the notify path must be allowlisted or deliveries will fail with an authentication error before reaching the cartridge.
- 6 Confirm every sellable product carries obHsCode Across the real catalogue, not just the product you tested with.
- 7 Take one small real payment Confirm the order, the payment status, the custom attributes, and the callback delivery all behave as in sandbox before opening the payment method to shoppers.
Step 8
Troubleshooting
| Symptom | Likely cause |
|---|---|
configuration_error in the logs, checkout rejected | A missing or invalid obInstallationId, a missing webhook secret, a non-HTTPS service URL, or a live key pointed at a non-production origin. |
Checkout rejected with missing_hs_code | A product in the basket has no obHsCode value. |
| Webhooks are refused with an authentication error | Storefront password protection in front of the notify path, a wrong obWebhookSecret, clock skew beyond 300 seconds, or an event delivered for the other rail. |
| Orders stay unplaced after an authentication challenge | The reconcile job is disabled. Enable OpenBorder-ReconcileAttempts on its hourly trigger. |
payment_in_progress at checkout | A prior attempt is genuinely in flight. Keep checkout on hold and do not submit another payment while the reconcile job confirms it — this is the single-flight fence doing its job, not an error to retry through. |
An attempt is flagged needsReview | An unknown provider outcome, a response mismatch, or a capture recovered onto an order that is no longer payable. Resolve it manually against the Open Border dashboard before clearing the hold; it stays the order’s authorisation fence until you do. |
| The payment method never appears | The cartridge path is wrong or another cartridge overriding checkout services sits ahead of it. Both Open Border cartridges must precede app_storefront_base. |
Step 9
Upgrade and remove
- 1 Verify the new artifact’s checksum Same check as the initial install. Never install an unverified archive.
- 2 Upload the new cartridges as a new code version Alongside the old one, then activate it. Rollback is re-activating the previous code version, which is why you keep it.
- 3 Re-import the new site_import archive Imports are additive and idempotent for these types.
- 4 Re-run the test-payment checks Custom objects, site preferences, and orders survive an upgrade untouched, but the verification is what tells you the new code version is wired correctly.
To remove: disable the OPENBORDER_CREDIT payment method, disable both jobs, remove both cartridges from the cartridge path and re-activate it, then delete the webhook endpoint in the Open Border dashboard. Resolve every non-terminal attempt before you start — removing the jobs removes the repair loop.