← Back to solutions
PluginPHPPaid

WP Remote Payment Client

WooCommerce gateway that takes payment through a gateway contracted to another site. It creates a shadow order remotely, returns a payment link, and moves the local order on an HMAC-signed, token-authenticated callback: with every exchange written to a log table.

WP Remote Payment Client

Stack

PHPWordPressWooCommerceREST APIJWTHMACMySQL

The problem

A shop needed to accept payment through a gateway that was contracted to a different site. Buyers had to be sent somewhere else to pay, and everything after that was guesswork: the shop had no way to learn the outcome, so an operator checked the other system by hand and moved orders along. Paid orders sat unfulfilled; abandoned ones looked identical to paid ones.

Naive versions of this integration fail in two specific ways. Either the callback endpoint is left open, so anyone who learns the URL can mark any order paid, and the shop believes it. Or the two systems keep separate order records that drift apart, and reconciling them becomes a weekly chore.

Before → After

BeforeAfter
Buyers sent off-site to pay with no way back into the orderA checkout gateway that returns a payment link and follows it through
Payment outcome learned by a person checking another systemSigned callback moves the order to its real status automatically
A callback URL anyone could callToken-authenticated endpoints with HMAC-signed payloads
Two systems, two order records, weekly reconciliationA shadow order linked by source and origin id: lookups, not reconciliation
Failures invisible until a customer complainedEvery remote exchange written to a log table with status and payload
Wiring a new partner site meant a code changeEndpoints, secret, token and provider set in the gateway settings

How it works

  1. The buyer picks the gateway. It registers as a normal WooCommerce payment method, so it appears at checkout beside every other option and needs no theme work.
  2. A shadow order is created remotely. The order is serialised and sent to the partner site, which creates its own matching order and returns a payment link. The buyer is redirected to it.
  3. Both sides stay addressable.The shadow order carries the origin order id and a source marker, so either system can find the other's record by meta query. There is no separate mapping table to drift.
  4. Payment result comes back signed. The callback endpoint requires a token, and the payload carries an HMAC signature verified against a shared secret with a timing-safe comparison. Only then is the local order status changed.
  5. Every exchange is logged. A dedicated table records the order, the remote order id, the source, the status, the callback URL and the raw payload, so a disputed payment is a query, not an investigation.
  6. Status changes propagate. A handler watches local order status and keeps the remote side informed, so cancelling or refunding on one side does not leave the other stale.

Key features

  • WooCommerce payment gateway: appears at checkout like any other method
  • Shadow order creation on a remote site with payment link return
  • HMAC-SHA256 request signing with timing-safe verification
  • Token-authenticated REST endpoints for link, lookup and callback
  • Order matching by source and origin id: no mapping table
  • Remote exchange log table with status and payload
  • Order status change propagation back to the remote side
  • Endpoints, secret, token, provider and payment method all in gateway settings

Installation

  1. Upload the plugin folder to /wp-content/plugins/ and activate it
  2. Run the bundled migration to create the remote order log table
  3. Open WooCommerce → Settings → Payments and enable the external site gateway
  4. Fill in the three remote endpoints, the shared secret, the API token and the provider name
  5. Place a test order and confirm the callback moves it to a paid status

Open for contract collaboration

I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.

Schedule a 30-min call