PlaceToPay — VoidPostCapture
Complexity: low
Generated by: Grace pipeline run run-2026-05-21T23-32-25-523Z-5aba32
Summary
Implement VoidPostCapture payment method for PlaceToPay connector. Technical Specification — PlaceToPay
Scope
Technical Specification — PlaceToPay
1. Connector Profile
| Property |
Value |
| Connector Name |
PlaceToPay |
| Primary Flow Scope |
Card Payments (Authorize, Capture, Void, VoidPostCapture, Refund, PSync, RSync) |
| API Family |
REST/JSON |
| Production Host |
https://checkout.placetopay.com/rest/gateway |
| Sandbox Host |
https://test.placetopay.com/rest/gateway |
| Regional Variants |
None documented; single international endpoint |
2. Authentication
Scheme: Custom HMAC-SHA256 digest (WS-Security style)
Every request body carries an auth object:
{
"auth": {
"login": "<merchantLogin>",
"tranKey": "<base64(SHA256(nonce_bytes + seed + secretKey))>",
"nonce": "<base64(random_16_bytes)>",
"seed": "<ISO-8601 UTC timestamp, e.g. 2024-01-15T10:30:00+00:00>"
}
}
Credentials required:
login — Merchant login identifier (plain string, sent as-is)
tran_key / secret — Merchant secret key used as the HMAC input (never sent directly)
Construction algorithm:
- Generate 16 cryptographically random bytes →
nonce_bytes
- Base64-encode
nonce_bytes → nonce
- Format current UTC time as
YYYY-MM-DDTHH:MM:SS+00:00 → seed
- Compute
SHA256(nonce_bytes || seed_bytes || secret_bytes) (concatenation of raw bytes)
- Base64-encode the SHA256 digest →
tranKey
Implementation notes:
nonce and seed are request-unique; replay is prevented by the timestamp.
- The
+00:00 suffix must be explicit (not Z).
- There are no HTTP Authorization headers; auth lives entirely in the JSON body.
3. Supported Flows
| Flow |
HTTP Method |
Path |
Notes |
| Authorize |
POST |
/process |
Card-present or card-not-present authorization |
| PSync |
POST |
/query |
Retrieve payment status by internalReference |
| Capture |
POST |
/transaction |
action=CHECKOUT — confirm/settle a pre-authorized payment |
| Void (pre-auth) |
POST |
/transaction |
action=VOID — ca |
Out of Scope
Not specified in techspec
Technical Constraints
- Follow existing connector patterns in the codebase
Full Tech Spec
Technical Specification — PlaceToPay
1. Connector Profile
| Property |
Value |
| Connector Name |
PlaceToPay |
| Primary Flow Scope |
Card Payments (Authorize, Capture, Void, VoidPostCapture, Refund, PSync, RSync) |
| API Family |
REST/JSON |
| Production Host |
https://checkout.placetopay.com/rest/gateway |
| Sandbox Host |
https://test.placetopay.com/rest/gateway |
| Regional Variants |
None documented; single international endpoint |
2. Authentication
Scheme: Custom HMAC-SHA256 digest (WS-Security style)
Every request body carries an auth object:
{
"auth": {
"login": "<merchantLogin>",
"tranKey": "<base64(SHA256(nonce_bytes + seed + secretKey))>",
"nonce": "<base64(random_16_bytes)>",
"seed": "<ISO-8601 UTC timestamp, e.g. 2024-01-15T10:30:00+00:00>"
}
}
Credentials required:
login — Merchant login identifier (plain string, sent as-is)
tran_key / secret — Merchant secret key used as the HMAC input (never sent directly)
Construction algorithm:
- Generate 16 cryptographically random bytes →
nonce_bytes
- Base64-encode
nonce_bytes → nonce
- Format current UTC time as
YYYY-MM-DDTHH:MM:SS+00:00 → seed
- Compute
SHA256(nonce_bytes || seed_bytes || secret_bytes) (concatenation of raw bytes)
- Base64-encode the SHA256 digest →
tranKey
Implementation notes:
nonce and seed are request-unique; replay is prevented by the timestamp.
- The
+00:00 suffix must be explicit (not Z).
- There are no HTTP Authorization headers; auth lives entirely in the JSON body.
3. Supported Flows
| Flow |
HTTP Method |
Path |
Notes |
| Authorize |
POST |
/process |
Card-present or card-not-present authorization |
| PSync |
POST |
/query |
Retrieve payment status by internalReference |
| Capture |
POST |
/transaction |
action=CHECKOUT — confirm/settle a pre-authorized payment |
| Void (pre-auth) |
POST |
/transaction |
action=VOID — cancel before capture |
| VoidPostCapture |
POST |
/transaction |
action=REVERSE with authorization — reverse a captured/settled transaction |
| Refund |
POST |
/transaction |
action=REVERSE with authorization — full reversal only (partial not supported) |
| RSync |
POST |
/query |
Retrieve refund/reversal status by internalReference |
| Webhooks |
N/A |
N/A |
Not implemented / not documented in current integration |
VoidPostCapture vs Void distinction: PlaceToPay uses action=VOID to cancel a transaction that has been authorized but not yet captured. Once a transaction is captured (action=CHECKOUT), the only way to reverse it is action=REVERSE. The authorization code returned in the capture response must be included in the Reverse request.
4. Request Schema Highlights
Authorize — POST /process
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"payment": {
"reference": "<connector_request_reference_id>",
"description": "<order description>",
"amount": {
"currency": "USD",
"total": 1000
}
},
"instrument": {
"card": {
"number": "4111111111111111",
"expiration": "12/26",
"cvv": "123"
}
},
"ipAddress": "<customer IP>",
"userAgent": "<browser user agent>"
}
- All fields are required for card payments.
amount.total is in minor units (cents).
expiration format: MM/YY (slash-delimited, 2-digit year).
ipAddress and userAgent come from browser_info in the authorize request.
Capture — POST /transaction
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"internalReference": 123456789,
"action": "CHECKOUT"
}
Void (pre-auth) — POST /transaction
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"internalReference": 123456789,
"action": "VOID"
}
VoidPostCapture — POST /transaction
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"internalReference": 123456789,
"action": "REVERSE",
"authorization": "<authorization_code_from_capture_response>"
}
internalReference: PlaceToPay's numeric transaction ID returned in the Authorize/Capture response (stored as connector_transaction_id). Must be parsed as u64.
authorization: The authorization code returned in the Capture response (connector_metadata). Required for post-capture reversal.
action values (enum, SCREAMING_SNAKE_CASE): REFUND, REVERSE, VOID, PROCESS, CHECKOUT
PSync / RSync — POST /query
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"internalReference": 123456789
}
Refund — POST /transaction
{
"auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" },
"internalReference": 123456789,
"action": "REVERSE",
"authorization": "<authorization_code>"
}
- Only full refunds are supported. Partial refund amount ≠ payment amount →
NotSupported error.
5. Response Schema Highlights
Payment Response (Authorize / Capture / Void / VoidPostCapture)
{
"status": {
"status": "APPROVED"
},
"internalReference": 123456789,
"authorization": "AUTH_CODE_STRING"
}
| Field |
Type |
Notes |
status.status |
enum (string) |
See Transaction Status Values below |
internalReference |
u64 |
PlaceToPay's numeric transaction ID; used as connector_transaction_id |
authorization |
string (optional) |
Authorization code; stored as connector_metadata; required for VoidPostCapture/Refund |
Transaction Status Values:
status Value |
Maps To AttemptStatus |
APPROVED |
Charged |
OK |
Charged |
FAILED |
Failure |
REJECTED |
Failure |
ERROR |
Failure |
PENDING |
Pending |
PENDING_VALIDATION |
Pending |
PENDING_PROCESS |
Pending |
Refund Response (Refund / RSync)
{
"status": {
"status": "REFUNDED"
},
"internalReference": 123456789
}
Refund Status Values:
status Value |
Maps To RefundStatus |
OK |
Success |
APPROVED |
Success |
REFUNDED |
Success |
FAILED |
Failure |
REJECTED |
Failure |
ERROR |
Failure |
PENDING |
Pending |
PENDING_PROCESS |
Pending |
PENDING_VALIDATION |
Pending |
6. Error Handling
Error Response Schema
{
"status": {
"status": "FAILED",
"message": "<human readable message>",
"reason": "<error code or reason>"
}
}
| HTTP Status |
status.status |
Cause |
| 400 |
FAILED |
Malformed request, missing required fields |
| 401 |
FAILED |
Invalid or expired authentication (bad login/tranKey/nonce) |
| 404 |
FAILED |
internalReference not found |
| 422 |
FAILED |
Business rule violation (e.g., attempting REVERSE on non-captured transaction) |
| 500 |
FAILED |
Internal PlaceToPay server error |
status.reason → mapped to ErrorResponse.code (falls back to NO_ERROR_CODE if absent)
status.message → mapped to ErrorResponse.message and ErrorResponse.reason (falls back to NO_ERROR_MESSAGE if absent)
connector_transaction_id is not populated in error responses
7. Webhooks / Async Notifications
Status: Not implemented in the current PlaceToPay connector integration.
- No webhook subscription endpoint is configured.
- No webhook signature verification logic exists.
- Async state changes must be polled via PSync (POST
/query).
- The
IncomingWebhook trait is implemented as a no-op stub.
Documented gaps:
- PlaceToPay's API may support push notifications (webhooks) for production environments, but the integration relies solely on polling for payment status updates.
- No retry policy, delivery format, or verification mechanism is documented or implemented.
8. References
- Connector implementation:
crates/integrations/connector-integration/src/connectors/placetopay.rs
- Transformer types:
crates/integrations/connector-integration/src/connectors/placetopay/transformers.rs
- Sandbox base URL:
https://test.placetopay.com/rest/gateway (from config/development.toml)
- Production base URL:
https://checkout.placetopay.com/rest/gateway (from config/production.toml)
- Field probe data:
data/field_probe/placetopay.json
- PlaceToPay official documentation:
https://docs.placetopay.com/ (not scraped; WebFetch not invoked per Phase 1c skip instruction)
- Integration test spec:
crates/internal/integration-tests/src/connector_specs/placetopay/
9. VoidPostCapture Implementation Notes
This section is specific to the VoidPostCapture flow being added.
Semantic distinction from pre-auth Void
| Scenario |
PlaceToPay Action |
When Used |
| Cancel before capture |
VOID |
Payment authorized but not yet settled |
| Reverse after capture |
REVERSE |
Payment captured/settled; full reversal needed |
Request construction for VoidPostCapture
- Retrieve
connector_transaction_id from the router data — this is internalReference (parse as u64).
- Retrieve
authorization from connector_metadata stored at capture time.
- Send POST to
/transaction with action=REVERSE, internalReference, and authorization.
Response handling
- Same
PlacetopayPaymentsResponse struct as Capture/Void — reuse existing response type.
- Status mapping follows the same
PlacetopayTransactionStatus → AttemptStatus conversion.
- A successful VoidPostCapture returns
APPROVED or OK status.
Constraint
authorization code must be available from the preceding Capture response. If not present, the REVERSE request may be rejected by PlaceToPay.
10. API Call Sequences
Standard Authorize → Capture → VoidPostCapture
POST /process → { internalReference: 123, authorization: "AUTH" } [Authorize]
POST /transaction → action=CHECKOUT, internalReference=123 [Capture]
POST /transaction → action=REVERSE, internalReference=123, authorization="AUTH" [VoidPostCapture]
Authorize → Void (pre-auth)
POST /process → { internalReference: 123 } [Authorize]
POST /transaction → action=VOID, internalReference=123 [Void]
11. Field Dependency Analysis
| Field |
Source |
Required For |
Notes |
auth.login |
ConnectorConfig.login |
All flows |
Merchant identifier |
auth.tranKey |
Derived (SHA256 of nonce+seed+secret) |
All flows |
Recomputed per request |
auth.nonce |
Random 16 bytes, base64 |
All flows |
Per-request uniqueness |
auth.seed |
Current UTC timestamp |
All flows |
Tied to nonce for replay protection |
internalReference |
Authorize response |
Capture, Void, VoidPostCapture, PSync, Refund, RSync |
Stored as connector_transaction_id |
authorization |
Capture/Authorize response (connector_metadata) |
VoidPostCapture, Refund |
Required for post-capture operations |
action |
Flow type |
Capture, Void, VoidPostCapture, Refund |
Enum: CHECKOUT/VOID/REVERSE |
payment.reference |
connector_request_reference_id |
Authorize |
Merchant-side order reference |
payment.amount.total |
minor_amount |
Authorize |
Minor unit currency amount |
instrument.card.* |
PaymentMethodData::Card |
Authorize |
Card details |
ipAddress |
browser_info.ip_address |
Authorize |
Required for card authorization |
userAgent |
browser_info.user_agent |
Authorize |
Required for card authorization |
12. UNDECIDED Fields
| Field |
Location |
Question |
authorization in VoidPostCapture |
Request body |
Confirm whether PlaceToPay requires authorization for REVERSE on all captured transactions, or only for specific card networks |
| Partial reversal |
VoidPostCapture |
Confirm whether PlaceToPay supports partial REVERSE amounts (currently assumed: no, same as Refund) |
action=REFUND |
PlacetopayNextAction enum |
Distinguish from REVERSE — may be for partial amounts or different reversal semantics |
PlaceToPay — VoidPostCapture
Complexity: low
Generated by: Grace pipeline run
run-2026-05-21T23-32-25-523Z-5aba32Summary
Implement VoidPostCapture payment method for PlaceToPay connector. Technical Specification — PlaceToPay
Scope
Technical Specification — PlaceToPay
1. Connector Profile
https://checkout.placetopay.com/rest/gatewayhttps://test.placetopay.com/rest/gateway2. Authentication
Scheme: Custom HMAC-SHA256 digest (WS-Security style)
Every request body carries an
authobject:{ "auth": { "login": "<merchantLogin>", "tranKey": "<base64(SHA256(nonce_bytes + seed + secretKey))>", "nonce": "<base64(random_16_bytes)>", "seed": "<ISO-8601 UTC timestamp, e.g. 2024-01-15T10:30:00+00:00>" } }Credentials required:
login— Merchant login identifier (plain string, sent as-is)tran_key/ secret — Merchant secret key used as the HMAC input (never sent directly)Construction algorithm:
nonce_bytesnonce_bytes→nonceYYYY-MM-DDTHH:MM:SS+00:00→seedSHA256(nonce_bytes || seed_bytes || secret_bytes)(concatenation of raw bytes)tranKeyImplementation notes:
nonceandseedare request-unique; replay is prevented by the timestamp.+00:00suffix must be explicit (notZ).3. Supported Flows
/process/queryinternalReference/transactionaction=CHECKOUT— confirm/settle a pre-authorized payment/transactionaction=VOID— caOut of Scope
Not specified in techspec
Technical Constraints
Full Tech Spec
Technical Specification — PlaceToPay
1. Connector Profile
https://checkout.placetopay.com/rest/gatewayhttps://test.placetopay.com/rest/gateway2. Authentication
Scheme: Custom HMAC-SHA256 digest (WS-Security style)
Every request body carries an
authobject:{ "auth": { "login": "<merchantLogin>", "tranKey": "<base64(SHA256(nonce_bytes + seed + secretKey))>", "nonce": "<base64(random_16_bytes)>", "seed": "<ISO-8601 UTC timestamp, e.g. 2024-01-15T10:30:00+00:00>" } }Credentials required:
login— Merchant login identifier (plain string, sent as-is)tran_key/ secret — Merchant secret key used as the HMAC input (never sent directly)Construction algorithm:
nonce_bytesnonce_bytes→nonceYYYY-MM-DDTHH:MM:SS+00:00→seedSHA256(nonce_bytes || seed_bytes || secret_bytes)(concatenation of raw bytes)tranKeyImplementation notes:
nonceandseedare request-unique; replay is prevented by the timestamp.+00:00suffix must be explicit (notZ).3. Supported Flows
/process/queryinternalReference/transactionaction=CHECKOUT— confirm/settle a pre-authorized payment/transactionaction=VOID— cancel before capture/transactionaction=REVERSEwithauthorization— reverse a captured/settled transaction/transactionaction=REVERSEwithauthorization— full reversal only (partial not supported)/queryinternalReference4. Request Schema Highlights
Authorize — POST
/process{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "payment": { "reference": "<connector_request_reference_id>", "description": "<order description>", "amount": { "currency": "USD", "total": 1000 } }, "instrument": { "card": { "number": "4111111111111111", "expiration": "12/26", "cvv": "123" } }, "ipAddress": "<customer IP>", "userAgent": "<browser user agent>" }amount.totalis in minor units (cents).expirationformat:MM/YY(slash-delimited, 2-digit year).ipAddressanduserAgentcome from browser_info in the authorize request.Capture — POST
/transaction{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "internalReference": 123456789, "action": "CHECKOUT" }Void (pre-auth) — POST
/transaction{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "internalReference": 123456789, "action": "VOID" }VoidPostCapture — POST
/transaction{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "internalReference": 123456789, "action": "REVERSE", "authorization": "<authorization_code_from_capture_response>" }internalReference: PlaceToPay's numeric transaction ID returned in the Authorize/Capture response (stored asconnector_transaction_id). Must be parsed asu64.authorization: The authorization code returned in the Capture response (connector_metadata). Required for post-capture reversal.actionvalues (enum, SCREAMING_SNAKE_CASE):REFUND,REVERSE,VOID,PROCESS,CHECKOUTPSync / RSync — POST
/query{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "internalReference": 123456789 }Refund — POST
/transaction{ "auth": { "login": "…", "tranKey": "…", "nonce": "…", "seed": "…" }, "internalReference": 123456789, "action": "REVERSE", "authorization": "<authorization_code>" }NotSupportederror.5. Response Schema Highlights
Payment Response (Authorize / Capture / Void / VoidPostCapture)
{ "status": { "status": "APPROVED" }, "internalReference": 123456789, "authorization": "AUTH_CODE_STRING" }status.statusinternalReferenceconnector_transaction_idauthorizationconnector_metadata; required for VoidPostCapture/RefundTransaction Status Values:
statusValueAPPROVEDChargedOKChargedFAILEDFailureREJECTEDFailureERRORFailurePENDINGPendingPENDING_VALIDATIONPendingPENDING_PROCESSPendingRefund Response (Refund / RSync)
{ "status": { "status": "REFUNDED" }, "internalReference": 123456789 }Refund Status Values:
statusValueOKSuccessAPPROVEDSuccessREFUNDEDSuccessFAILEDFailureREJECTEDFailureERRORFailurePENDINGPendingPENDING_PROCESSPendingPENDING_VALIDATIONPending6. Error Handling
Error Response Schema
{ "status": { "status": "FAILED", "message": "<human readable message>", "reason": "<error code or reason>" } }status.statusFAILEDFAILEDFAILEDinternalReferencenot foundFAILEDFAILEDstatus.reason→ mapped toErrorResponse.code(falls back toNO_ERROR_CODEif absent)status.message→ mapped toErrorResponse.messageandErrorResponse.reason(falls back toNO_ERROR_MESSAGEif absent)connector_transaction_idis not populated in error responses7. Webhooks / Async Notifications
Status: Not implemented in the current PlaceToPay connector integration.
/query).IncomingWebhooktrait is implemented as a no-op stub.Documented gaps:
8. References
crates/integrations/connector-integration/src/connectors/placetopay.rscrates/integrations/connector-integration/src/connectors/placetopay/transformers.rshttps://test.placetopay.com/rest/gateway(fromconfig/development.toml)https://checkout.placetopay.com/rest/gateway(fromconfig/production.toml)data/field_probe/placetopay.jsonhttps://docs.placetopay.com/(not scraped; WebFetch not invoked per Phase 1c skip instruction)crates/internal/integration-tests/src/connector_specs/placetopay/9. VoidPostCapture Implementation Notes
This section is specific to the
VoidPostCaptureflow being added.Semantic distinction from pre-auth Void
VOIDREVERSERequest construction for VoidPostCapture
connector_transaction_idfrom the router data — this isinternalReference(parse asu64).authorizationfromconnector_metadatastored at capture time./transactionwithaction=REVERSE,internalReference, andauthorization.Response handling
PlacetopayPaymentsResponsestruct as Capture/Void — reuse existing response type.PlacetopayTransactionStatus → AttemptStatusconversion.APPROVEDorOKstatus.Constraint
authorizationcode must be available from the preceding Capture response. If not present, the REVERSE request may be rejected by PlaceToPay.10. API Call Sequences
Standard Authorize → Capture → VoidPostCapture
Authorize → Void (pre-auth)
11. Field Dependency Analysis
auth.loginauth.tranKeyauth.nonceauth.seedinternalReferenceauthorizationactionpayment.referencepayment.amount.totalinstrument.card.*ipAddressuserAgent12. UNDECIDED Fields
authorizationin VoidPostCaptureauthorizationfor REVERSE on all captured transactions, or only for specific card networksaction=REFUND