conneqt / module-punchout
Punchout System
Package info
git.dev.epartment.nl/conneqt/m2/module-punchout
Type:magento2-module
pkg:composer/conneqt/module-punchout
This package is auto-updated.
Last update: 2026-06-05 13:43:32 UTC
README
conneqt/module-punchout
What this module does
This module adds PunchOut support to Magento 2 so a customer can start in a procurement system, punch into Magento, add products to a cart, and send the cart back to the procurement or ERP system.
The module currently supports:
- OCI punchout
- OCI AFAS variant
- cXML PunchOutSetupRequest / PunchOutOrderMessage flow
In short, the module does four things:
- Accepts a punchout login request from an external system.
- Maps that request to a Magento customer using a
PunchoutSystemandPunchoutLink. - Lets the customer shop inside Magento in a normal storefront session.
- Returns the selected cart back to the external system as OCI form fields or a cXML
PunchOutOrderMessage.
It also stores inbound and outbound traffic in a Request Log, which is useful when testing or troubleshooting integrations.
Contents
- Installation
- How it works
- Magento admin configuration
- Important files
- Testing with PunchOutCommerce tools
- Troubleshooting notes
Installation
In production, use the
--keep-generatedflag where appropriate.
Install from a zip file
- Unzip the module to
app/code/Conneqt/Punchout - Enable the module:
php bin/magento module:enable Conneqt_Punchout
- Apply database and data patches:
php bin/magento setup:upgrade
- Flush cache:
php bin/magento cache:flush
Install with Composer
composer require conneqt/module-punchout
php bin/magento module:enable Conneqt_Punchout
php bin/magento setup:upgrade
php bin/magento cache:flush
How it works
OCI flow
The procurement system sends an HTTP request to:
{base-url}/conneqt-punchout/index/loginController/Index/Login.phpvalidates the required OCI parameters:USERNAMEPASSWORDHOOK_URL
Helper/Login.phpfinds a matchingPunchoutLinkand verifies that:- the link contains identifier rows for
USERNAMEandPASSWORD - those values match the customer attributes
punchout_usernameandpunchout_password
- the link contains identifier rows for
If the request is valid, the customer is logged into Magento and the punchout request data is stored in the session.
While the customer shops, the observers:
Observer/AddToCart.phpObserver/RemoveFromCart.php
keep the punchout item table in sync with the quote.
When the customer opens checkout,
Observer/PunchoutAction.phpredirects the normal checkout flow to:/conneqt-punchout/index/customcheckoutBlock/Response/Data.phpandHelper/Data.phpconvert the quote into OCI response fields such asNEW_ITEM-...entries.view/frontend/templates/postData.phtmlauto-posts those fields back to the externalHOOK_URL.
cXML flow
The procurement system sends a cXML
PunchOutSetupRequestto:{base-url}/conneqt-punchout/index/authController/Index/Auth.phpparses the cXML request and extracts these values:From/Credential/@domainSender/Credential/IdentitySender/Credential/SharedSecretBuyerCookieBrowserFormPost/URL
Helper/CxmlLogin.phpvalidates the request against Magento configuration.If authentication succeeds, Magento creates a
RequestLogentry with the intermediate cXML auth status and returns a cXMLPunchOutSetupResponsewith a Magento start page URL.That start page points to
Controller/Index/CreateSession.php, which re-opens the stored request, logs the customer into Magento, and writes the final punchout session data into Magento's session.The customer shops in Magento.
At checkout return time,
Helper/Data.php::createCxmlData()builds a cXMLPunchOutOrderMessage.view/frontend/templates/postData.phtmlposts it back to theBrowserFormPost/URLas thecXML-urlencodedform field.
Magento admin configuration
Global configuration
Path:
Stores > Configuration > Conneqt Punchout > General
Defined in:
etc/adminhtml/system.xml
Important settings:
- Enable: must be set to
Yes - Max Description length: used when generating outbound item descriptions
- Magento Attribute Mapping: available for additional mapping use cases
Punchout System
Path:
Conneqt > PunchoutSystem
Defined in:
view/adminhtml/ui_component/conneqt_punchout_punchoutsystem_form.xml
Fields:
- System Name
- Type
ocioci_afascxml
- Shared Secret
- shown for
cxml - used by
Helper/CxmlLogin.php
- shown for
Punchout Link
Path:
Conneqt > PunchoutLink
Defined in:
view/adminhtml/ui_component/conneqt_punchout_punchoutlink_form.xml
Fields:
- Website ID (
store_idin the form) - customer_id
- punchoutsystem_id
- Identifier Mapping dynamic rows
- Identifier
- Value
This entity links:
- a Magento website
- a Magento customer
- a punchout system definition
- the values used to authenticate the punchout request
OCI identifier mapping
For OCI, create at least these two rows:
| Identifier | Value |
|---|---|
USERNAME | the punchout username |
PASSWORD | the punchout password |
cXML identifier mapping
For cXML, the current implementation expects the mapping to work like this:
- Identifier = the value from
From/Credential/@domain - Value = the value from
Sender/Credential/Identity
Example:
| Identifier | Value |
|---|---|
NetworkId | buyer@example |
The cXML shared secret is not stored in the link. It is read from the selected PunchoutSystem record.
Customer attributes
Defined by:
Setup/Patch/Data/CustomerAttribute.php
Added customer attributes:
punchout_usernamepunchout_password
These are used directly by the OCI login flow in Helper/Login.php.
For OCI, make sure the customer values match the values used in the PunchoutLink identifier mapping.
Note: there is also
Setup/Patch/Data/CustomerSecretKeyAttribute.php, but the current cXML login flow does not use that customer attribute for authentication. cXML authentication usesPunchoutSystem.shared_secretinstead.
Request Log
Path:
Conneqt > RequestLog
Stored in:
conneqt_punchout_requestlog- defined in
etc/db_schema.xml
Useful statuses from Api/Data/RequestLogInterface.php:
| Status | Meaning |
|---|---|
0 | Invalid Request |
1 | Session Active |
2 | Closed |
3 | cXML auth complete |
4 | cXML session active |
Use the request log to confirm:
- whether Magento accepted the inbound punchout request
- whether cXML authentication completed
- what request data was received
- what response data Magento sent back
Important files
The files below are a good starting point when you want to understand or debug the module.
| File | What it does |
|---|---|
Controller/Index/Login.php | Entry point for OCI punchout login requests |
Helper/Login.php | Matches OCI requests to PunchoutLink + customer credentials and writes request logs |
Controller/Index/Auth.php | Entry point for cXML PunchOutSetupRequest |
Controller/Index/CreateSession.php | Completes the cXML login by converting the temporary auth token into a Magento session |
Helper/CxmlLogin.php | cXML-specific authentication and setup response generation |
Helper/Data.php | Converts the Magento quote into OCI or cXML response payloads |
Block/Response/Data.php | Makes the punchout response data available to the frontend template |
view/frontend/templates/postData.phtml | Auto-posts the generated payload back to the procurement system |
Observer/PunchoutAction.php | Redirects checkout to the punchout return page |
Observer/AddToCart.php | Stores punchout item snapshots when products are added |
Observer/RemoveFromCart.php | Removes punchout item snapshots when products are removed |
view/adminhtml/ui_component/conneqt_punchout_punchoutsystem_form.xml | Admin form definition for punchout system records |
view/adminhtml/ui_component/conneqt_punchout_punchoutlink_form.xml | Admin form definition for link records |
etc/db_schema.xml | Defines the punchoutsystem, punchoutlink, requestlog, and punchoutitems tables |
Testing with PunchOutCommerce tools
These instructions are based on the current implementation in this module.
OCI RoundTrip Tester
Tool:
https://punchoutcommerce.com/tools/oci-roundtrip-tester
Magento setup before testing
Enable the module in:
Stores > Configuration > Conneqt Punchout > General > Enable = YesCreate or choose a customer.
Fill the customer's custom attributes:
punchout_usernamepunchout_password
Create a
PunchoutSystemwith:- Type =
OCIorOCI AFAS
- Type =
Create a
PunchoutLinkwith:- Website ID = website for the customer/storefront
- customer_id = the customer that should be logged in
- punchoutsystem_id = the OCI system you created
Identifier Mapping rows:
Identifier Value USERNAMEsame as customer punchout_usernamePASSWORDsame as customer punchout_password

Which tester fields map to Magento?
On the OCI tester page, use these values:
| OCI tester field | Fill in |
|---|---|
URL | {base-url}/conneqt-punchout/index/login |
USERNAME | the same value as PunchoutLink identifier USERNAME and customer punchout_username |
PASSWORD | the same value as PunchoutLink identifier PASSWORD and customer punchout_password |
HOOK_URL | leave the tester default or use your own receiver URL |
~TARGET | usually leave default |
~OkCode | usually leave default |
~CALLER | usually leave default |
| extra name/value pairs | optional; this module ignores most extra OCI fields unless you custom-handle them |
Test steps
- Open the OCI tester page.
- Fill in the fields from the table above.
- Submit the tester form.
- Magento should log in the configured customer and open the storefront.
- Add one or more products to the cart.
- Open checkout or the cart flow that triggers checkout redirection.
- Magento should redirect to the punchout response page and auto-post the cart back to the tester
HOOK_URL. - The tester should show the returned OCI form fields.
If OCI login fails
Check:
- module enabled flag
PunchoutLinkbelongs to the correct website and customer- link has
USERNAMEandPASSWORDidentifier rows - customer
punchout_usernameandpunchout_passwordmatch exactly - request log entry in
Conneqt > RequestLog
cXML PunchOut Tester
Tool:
https://punchoutcommerce.com/tools/cxml-punchout-tester
Magento setup before testing
Enable the module:
Stores > Configuration > Conneqt Punchout > General > Enable = YesCreate or choose a customer.
Create a
PunchoutSystemwith:- Type =
CXML - Shared Secret = the value you will also enter into the tester as
SharedSecret
- Type =
Create a
PunchoutLinkwith:- Website ID = storefront website to use
- customer_id = customer to log in
- punchoutsystem_id = the CXML punchout system
Identifier Mapping row where:
Identifier Value same as FromDomainsame as SenderIdentity
Example:
Identifier Value NetworkIdbuyer@example
Important: in the current implementation, cXML authentication is matched using
From/Credential/@domain,Sender/Credential/Identity, andSender/Credential/SharedSecret.
Which tester fields map to Magento?
The cXML tester has a top URL field and a variable editor / XML template.
Use the values below:
| cXML tester field / variable | Fill in |
|---|---|
URL | {base-url}/conneqt-punchout/index/auth |
SupplierSetupURL | {base-url}/conneqt-punchout/index/auth |
FromDomain | same as the Identifier value in Magento, for example NetworkId |
SenderIdentity | same as the Value in the Magento identifier row |
SharedSecret | same as PunchoutSystem > Shared Secret |
PunchoutOrderReceiver | usually leave the tester default https://punchoutcommerce.com/tools/cxml-punchout-return |
BuyerCookie | leave generated/default value or enter your own test value |
FromIdentity | not validated by the current module; can be left as your buyer identifier |
ToDomain / ToIdentity | not validated by the current module; can be left at tester defaults or supplier identifiers |
Where to fill the values in the cXML tester page
The tester page usually shows:
- a top URL field
- a variable list with names like
FromDomain,SenderIdentity,SharedSecret,BuyerCookie,PunchoutOrderReceiver, andSupplierSetupURL - the full XML textarea containing placeholders such as
@FromDomain@and@SharedSecret@
Recommended approach:
Set the top URL field to:
{base-url}/conneqt-punchout/index/authIn the variable list, set:
FromDomainSenderIdentitySharedSecretSupplierSetupURL
Leave
PunchoutOrderReceiverpointing to the tester return URL unless you want to receive the cXML elsewhere.Make sure the XML template contains:
<BrowserFormPost><URL>@PunchoutOrderReceiver@</URL></BrowserFormPost><SupplierSetup><URL>@SupplierSetupURL@</URL></SupplierSetup>
Test steps
- Open the cXML tester page.
- Fill in the fields and variables from the mapping above.
- Submit the tester.
- Magento should authenticate the cXML request and return a
PunchOutSetupResponse. - Follow the returned start page into Magento.
- Add products to the cart.
- Open checkout so the punchout response page is triggered.
- Magento should post a
cXML-urlencodedfield back to the tester'sPunchoutOrderReceiverURL. - The tester should display the returned
PunchOutOrderMessage.
If cXML login fails
Check:
- module enabled flag
PunchoutSystemtype iscxmlPunchoutSystem.shared_secretmatches the testerSharedSecretPunchoutLinkpoints to the correct customer and system- identifier mapping matches
FromDomain->SenderIdentity Conneqt > RequestLogstatus changes toCXML Auth completeand thenCXML Session Active
Troubleshooting notes
The frontend route for this module is defined in
etc/frontend/routes.xmlas:conneqt-punchoutNormal public entry URLs are:
/conneqt-punchout/index/login /conneqt-punchout/index/auth /conneqt-punchout/index/customcheckoutObserver/PunchoutAction.phponly redirects checkout when punchout session data contains aHOOK_URL.The cXML storefront return flow uses
Helper/Data.php::createCxmlData(). The separate methodHelper/CxmlLogin.php::generatePunchoutOrderMessage()exists, but it is not the main storefront return path used by thepostData.phtmltemplate.Controller/Index/CustomCheckoutCart.phpcurrently looks like development/debug code and is not part of the main documented flow.If the cart returns empty data, first verify that products were added after the punchout session was created and that
conneqt_punchout_punchoutitemsis being populated.
Database entities created by this module
Defined in etc/db_schema.xml:
conneqt_punchout_punchoutsystemconneqt_punchout_punchoutlinkconneqt_punchout_requestlogconneqt_punchout_punchoutitems
These tables store:
- punchout system definitions
- customer-to-system authentication mappings
- inbound/outbound request logs
- staged item data used when building outbound punchout responses