How to add and save a card with CopyAndPay


Our full CopyAndPay documentation is available here

The info below is additional information for a standalone transaction to store a card.
This is when a customer is not storing the card at checkout, but simply adding the card to their profile without purchasing a good or service.

When a customer adds a card, a PA transaction needs to be processed.

This will validate the card and once validated, store the card details and return a payload.
See more on payment types

The payload (response from our systems) will include a registrationID, which you can save as the token of the card. You can then make payments on this stored card by referencing its token (registrationID).

From an implementation perspective what this means is that you simply change the CheckoutID request from Step 1 (CopyAndPay) to include the following :

paymentType = PA
Amount = ZAR 1.00

Main reason why you cannot do a RG and then a DB, is that the RG does not go to the bank and therefore will not be authenticated (the banks only process transactions with an amount - we also cannot attach an amount to the RG, since amounts will differ in the future). Processing an RG only therefore may store a card that cannot be billed.

Since there is no checkout when a customer adds a card ; i.e,. your workflow is

- Add a card
- Book a service
- On return, select a card for payment / add a new card to checkout with


1. Send request to store the card

A R1.00 PA is done to check that the card being added is valid, before you store the card for future billing.

This R1.00 amount should return to the customer's account after a period ; i.e, their balance will increase by R1.00 when the PA falls away (reservation period differs from bank to bank).

If this R1.00 PA is not done, first of all the card storage transaction cannot be 3DSecure authenticated and secondly, you may store cards that later cannot be billed at a later stage. This does not ensure that you can charge the full amount (since most likely the basket value would be greater than R1.00), but it at least checks with the bank that the card is valid.

Sample code below:

function request() {
$url = "";
$data = "authentication.userId=XXXXXXXXX".
"&authentication.password=XXXXXX" .
"&authentication.entityId=XXXXXXXXXXXX" .
"&amount=1.00" .
"&currency=ZAR" .


You can then store the card (the registrationID) in your database against the customer's user profile, ONLY IF the PA transaction is successful.

Please use the 3DSECURE channel ID as the authentication.entityId, for this PA transaction. This will make sure the user authenticates the card via 3DSecure with their bank before the card is added.


2. Your systems store card token

The payload (response from our systems) will include a registrationID, which you can save as the token of the card. You can then make payments on this stored card by referencing its token. Please only store the token in your database if the PA transaction is successful


3. When amount is due, stored card is billed

curl{id}/payments \
 -d "authentication.userId=XXXXXXXXX" \
 -d "authentication.password=XXXXXXXx" \
 -d "authentication.entityId=XXXXXXX" \
 -d "amount=92.00" \
 -d "currency=ZAR" \
 -d "paymentType=DB"
 -d "recurringType=REPEATED"

Please note that the entity ID here should be the recurring entityID -d "authentication.entityId=XXXXXXXX" \


Have more questions? Submit a request


Powered by Zendesk