Account funding transaction with gateway 3DS

From a PCI DSS-compliant environment, create a direct server-to-server integration with the CardCorp gateway.

🚧

PCI -DSS 4.x

Your website payment pages must comply with PCI DSS v4.x.
For more details, see the gateway PCI compliance documentation.

Learn how to perform an account funding transaction with 3DS validation with the CardCorp gateway MPI.


1. Create the payment request

Use a POSTrequest to the gateway to the payments endpoint with the payment type, amount, currency, and required attributes.

Here is an example of the request to create an account funding transaction, and how to save a card in the payment gateway for one-click checkout.

Create the payment request

curl https://eu-test.oppwa.com/v1/payments \
-d "entityId=(Channel ID)" \
-d "amount=20.00" \
-d "currency=EUR" \
-d "paymentType=DB" \
-d "merchantTransactionId=P123" \
-d "paymentBrand=VISA" \
-d "card.number=4711100000000000" \
-d "card.holder=Joe Smith" \
-d "card.expiryMonth=05" \
-d "card.expiryYear=2030" \
-d "card.cvv=123" \
-d "billing.street1=Ave. Diagonal 611" \
-d "billing.city=Barcelona" \
-d "billing.country=ES" \
-d "billing.postcode=08028" \
-d "[email protected]" \
-d "customer.ip=2001:8a0:7f4b:1b00:dd4e:2bf6:1fb8:56af" \
-d "customer.givenName=Joe" \
-d "customer.surname=Smith" \
-d "customer.phone=442880090001" \
-d "customer.merchantCustomerId=CUST01" \
-d "shopperResultUrl=https://docs.oppwa.com/tutorials/server-to-server/standalone3DS#step3" \
-d "merchant.city=Vancouver" \
-d "recipient.givenName=Jane" \
-d "recipient.surname=Smith" \
-d "recipient.state=QC" \
-d "recipient.country=CAN" \
-d "recipient.accountNumberType=RTN_AND_BANK_ACCOUNT" \
-d "recipient.accountNumber=1234567890" \
-d "recipient.birthDate=1985-01-01" \
-d "recipient.phone=0123456789" \
-d "customer.browser.acceptHeader=text/html" \
-d "customer.browser.screenColorDepth=48" \
-d "customer.browser.javaEnabled=false" \
-d "customer.browser.language=en" \
-d "customer.browser.screenHeight=1200" \
-d "customer.browser.screenWidth=1600" \
-d "customer.browser.timezone=60" \
-d "customer.browser.challengeWindow=4" \
-d "customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" \
-d "customParameters[TransactionTypeIdentifier]=F07" \
-d "customParameters[DateOfFunds]=250901" \
-d "customParameters[AdditionalTrace]=ABC123" \
-d "customParameters[CreditSenderName]=John Smith" \
-d "customParameters[CreditSenderAddress]=Grillparzerstr 18|Munich|BAV|DEU|81675" \
-d "customParameters[CreditSenderCity]=Munich" \
-d "customParameters[CreditSenderState]=BAV" \
-d "customParameters[CreditSenderCountry]=DEU" \
-d "threeDSecure.challengeIndicator=04" \
-d "customParameters[3DS2_enrolled]=true" \
-d "customParameters[3DS2_flow]=challenge" \
-d "testMode=EXTERNAL" \
-H "Authorization: Bearer (auth_token)"
curl https://eu-test.oppwa.com/v1/payments \
-d "entityId=(Channel ID)" \
-d "amount=20.00" \
-d "currency=EUR" \
-d "paymentType=DB" \
-d "merchantTransactionId=P123" \
-d "paymentBrand=VISA" \
-d "card.number=4711100000000000" \
-d "card.holder=Joe Smith" \
-d "card.expiryMonth=05" \
-d "card.expiryYear=2030" \
-d "card.cvv=123" \
-d "billing.street1=Ave. Diagonal 611" \
-d "billing.city=Barcelona" \
-d "billing.country=ES" \
-d "billing.postcode=08028" \
-d "[email protected]" \
-d "customer.ip=2001:8a0:7f4b:1b00:dd4e:2bf6:1fb8:56af"\
-d "customer.givenName=Joe" \
-d "customer.surname=Smith" \
-d "customer.phone=442880090001" \
-d "customer.merchantCustomerId=CUST01" \
-d "shopperResultUrl=https://docs.oppwa.com/tutorials/server-to-server/standalone3DS#step3" \
-d "merchant.city=Vancouver" \
-d "recipient.givenName=Jane" \
-d "recipient.surname=Smith" \
-d "recipient.state=QC" \
-d "recipient.country=CAN" \
-d "recipient.accountNumberType=RTN_AND_BANK_ACCOUNT" \
-d "recipient.accountNumber=1234567890" \
-d "recipient.birthDate=1985-01-01" \
-d "recipient.phone=0123456789" \
-d "customer.browser.acceptHeader=text/html" \
-d "customer.browser.screenColorDepth=48"\
-d "customer.browser.javaEnabled=false"\
-d "customer.browser.language=en" \
-d "customer.browser.screenHeight=1200" \
-d "customer.browser.screenWidth=1600" \
-d "customer.browser.timezone=60" \
-d "customer.browser.challengeWindow=4" \
-d "customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)" \
-d "customParameters[TransactionTypeIdentifier]=F07" \
-d "customParameters[DateOfFunds]=250901" \
-d "customParameters[AdditionalTrace]=ABC123" \
-d "customParameters[CreditSenderName]=John Smith" \
-d "customParameters[CreditSenderAddress]=Grillparzerstr 18|Munich|BAV|DEU|81675" \
-d "customParameters[CreditSenderCity]=Munich" \
-d "customParameters[CreditSenderState]=BAV" \
-d "customParameters[CreditSenderCountry]=DEU" \
-d "threeDSecure.challengeIndicator=04" \
-d "customParameters[3DS2_enrolled]=true" \
-d "customParameters[3DS2_flow]=challenge" \
-d "testMode=EXTERNAL" \ 
-d "standingInstruction.type=UNSCHEDULED" \
-d "standingInstruction.mode=INITIAL" \
-d "standingInstruction.source=CIT" \  
-d "createRegistration=true" \
-H "Authorization: Bearer (auth_token)"

Replace the example values with your values and replace the {channelId} and {auth_token} with your API credentials.


Account funding transaction request parameters table

This table includes the parameters for the iframe checkout and the account funding transaction parameters required by the Card Schemes.

KeyExample ValueValue Format / OptionsMandatory
entityId{channelId}AN32Yes
amount100.00N10.N2Yes
currencyEURA3Yes
paymentBrandMASTERVISA, MASTER, and so on, as in Gateway documentationYes
card detailsYes
paymentTypeDBDB debit or PA preauthorisation. For PA use the back office API to capture the amount.Yes
integritytrueBoolean, checkout securityYes
merchantTransactionIdABC123AN..255Recommended
billing addressYes for 3DS
customer detailsYes - email and ip
customer.browserDefine browser window sizeRecommended for 3DS
shopperResultUrlURL to redirect toYes for 3DS
merchant.cityVancouverANS13Yes
recipient.givenNameJaneAN48Yes
recipient.surnameSmithAN48Yes
recipient.stateQCANS..3Mandatory for: Mastercard Send Funding to US and Canada
recipient.countryCANA3Mandatory for: Mastercard Send Funding to US and Canada
recipient.street123 Street RoadANS..25Mandatory for: Mastercard Send Funding to US and Canada
recipient.cityVancouverANS..15Mandatory for: Mastercard Send Funding to US and Canada
recipient.postcodeL4J 1V1ANS..10Mandatory for: Mastercard Send Funding to US and Canada
recipient.
accountNumberType
RTNAND
BANK_ACCOUNT
Indicates type of recipient's account. Possible values are:
OTHER RTN_AND_BANK_ACCOUNT IBAN
EMAIL PHONE_NUMBER BAN_AND_BIC WALLET_ID SOCIAL_NETWORK_ID
Yes
recipient.accountNumber1234567890ANS..50Yes
customParameters[
TransactionTypeIdentifier]
F64Possible values are:
F07 - Funding General Person to Person Transfer
F08 - Funding Person to Person Transfer to Card Account
F52 - Funding General Transfer to Own Account
F54 - Funding Payment of Own Credit Card Bill
F61 - Funding Transfer to Own Staged Digital Wallet Account
F64 - Funding Transfer to Own Debit or Prepaid Card Account
Mandatory for: Mastercard Send Funding transactions
customParameters[
CreditSenderName]
John SmithAN..30Yes
customParameters[
CreditSenderAddress]
Grillparzerstr 18|Munich|BAV|
DEU|81675
AN.. 35
Street|City|StateCode(US Only)|ISO3166 CountryCode|PostalCode
Yes
customParameters[
CreditSenderCity]
MunichAN..25Yes
customParameters[
CreditSenderState]
BAVAN3Yes
customParameters[
CreditSenderCountry]
DEUAN3Yes
threeDSecure.
challengeIndicator
The recommended value is 04.Yes in UK and EEA
customParametersWe recommend adding custom parameters to uniquely identify the customer, order, and purchase type. The custom data you send in these parameters will be returned in the payment response. .You can use these parameters to pair and match information from the payment gateway with your business systems. You can create an unlimited number of unique and properly-named custom parametersRecommended
standingInstruction.typeUNSCHEDULEDTo save card for one-click checkout
standingInstruction.modeINITIALTo save card for one-click checkout
standingInstruction.sourceCITTo save card for one-click checkout
createRegistrationtrueOptional to save card for one-click checkout

Here are some notes about the parameters in the above requests.

When you will be saving the card, you must use the following standingInstruction parameters.

When you are testing your integration, you can use the following parameters.

ParametersNotes
customParameters[3DS2_enrolled]This parameter is for the test environment only. Set to true for any card to specify that the card is enrolled in 3DS. Or instead of the 3DS test parameters, you can use 3DS test cards.
customParameters[3DS2_flow]This parameter is for the test environment only. Set to challenge to force a 3DS challenge, or frictionless. Or instead of the 3DS test parameters, you can use 3DS test cards.
testModeThis parameter is for the test environment only. Set to EXTERNAL to send the transaction to the acquirer's test environment. Set to INTERNAL to process the transaction in the gateway only.

For a one-click checkout, from a single payment response, get the id, registrationId and 3DS parameters to use in repeated payment requests.


Test in the gateway playground

To test these requests, you can use the gateway playground at Gateway documentation and playground for synchronous payments and the following data.

entityId={channelId}
amount=20.00
currency=EUR
paymentType=DB
merchantTransactionId=P223
paymentBrand=VISA
card.number=47111000000000000
card.holder=Joe Smith
card.expiryMonth=05
card.expiryYear=2030
card.cvv=123
billing.street1=Calle Principal 123
billing.city=Barcelona
billing.country=ES
billing.postcode=08123
[email protected]
customer.ip=2001:8a0:7f4b:1b00:dd4e:2bf6:1fb8:56af
customer.givenName=Joe
customer.surname=Smith
customer.phone=34667666666
customer.merchantCustomerId=CUST11
shopperResultUrl=https://example.com/shopperresult
merchant.city=Vancouver
recipient.givenName=Jane
recipient.surname=Smith
recipient.state=QC
recipient.country=CAN
recipient.accountNumberType=RTN_AND_BANK_ACCOUNT
recipient.accountNumber=1234567890
recipient.birthDate=1985-01-01
recipient.phone=0123456789
customer.browser.screenColorDepth=48
customer.browser.javaEnabled=false
customer.browser.language=en
customer.browser.screenHeight=1200
customer.browser.screenWidth=1600
customer.browser.timezone=60
customer.browser.challengeWindow=4
customer.browser.userAgent=Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)
customParameters[TransactionTypeIdentifier]=F07
customParameters[DateOfFunds]=250901
customParameters[AdditionalTrace]=ABC123
customParameters[CreditSenderName]=John Smith
customParameters[CreditSenderAddress]=Grillparzerstr 18|Munich|BAV|DEU|81675
customParameters[CreditSenderCity]=Munich
customParameters[CreditSenderState]=BAV
customParameters[CreditSenderCountry]=DEU
threeDSecure.challengeIndicator=04
customParameters[CRMCustomerID]=CUST01
customParameters[OrderID]=SP-00100
customParameters[PaymentType]=AFT
threeDSecure.challengeIndicator=04
customParameters[3DS2_enrolled]=true
customParameters[3DS2_flow]=challenge
testMode=EXTERNAL

Use the following additional parameters to save a customer card in the gateway, for example, for one-click checkout.

standingInstruction.type=UNSCHEDULED
standingInstruction.mode=INITIAL
standingInstruction.source=CIT
createRegistration=true

When the payment is approved, get the registrationId from the response object and the 3DS data.


2. Get the 3DS redirect data from the response

The payment has a status of transaction pending because you must use the 3DS details in the response to redirect the cardholder to the 3DS system so they can verify the transaction.

Example response

{
  "id":"8ac7a4a09167849e01916ae343dd3de8",
  "paymentType":"DB",
  "paymentBrand":"MASTER",
  "merchantTransactionId":"P223",
  "result":{
    "code":"000.200.000",
    "description":"transaction pending"
  },
  "resultDetails":{
    "clearingInstituteName":"SecureTrading Omnipay Demo",
    "merchantAccountId":"8ac7a4c890fc748b0190fe70998c0248"
  },
  "card":{
    "bin":"520000",
    "last4Digits":"0049",
    "holder":"Joe Smith",
    "expiryMonth":"05",
    "expiryYear":"2030"
  },
  "customer":{
    "givenName":"Joe",
    "surname":"Smith",
    "merchantCustomerId":"CUST11",
    "phone":"34667666666",
    "email":"[email protected]",
    "ip":"2001:8a0:7f4b:1b00:dd4e:2bf6:1fb8:56af",
    "browser":{
      "language":"en",
      "screenHeight":"1200",
      "screenWidth":"1600",
      "timezone":"60",
      "userAgent":"Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)",
      "javaEnabled":"false",
      "screenColorDepth":"48",
      "challengeWindow":"4"
    }
  },
  "billing":{
    "street1":"Calle Principal 123",
    "city":"Barcelona",
    "postcode":"08123",
    "country":"ES"
  },
  "threeDSecure":{
    "challengeIndicator":"04"
  },
  "customParameters":{
    "3DS2_flow":"challenge",
    "3DS_enrolled":"true"
  },
  "redirect":{
 "url":"https://test.oppwa.com/connectors/asyncresponse_simulator;jsessionid=AF479520ED64C237BE42DF8958D162B0.uat01-vm-con03?asyncsource=ACI_3DS_2&type=methodRedirect&cdkForward=true&ndcid=8ac7a4c890fc748b0190fe6ad56b0241_2e9b5ad5cb9a421eafda6c123119da27",
    "parameters":[
      
    ],
    "preconditions":[
      {
        "origin":"iframe#hidden",
        "waitUntil":"iframe#load",
        "description":"Hidden iframe post for 3D Secure 2.0",
        "url":"https://test.ppipe.net/connectors/demo/submit?action=ACI3DS2AccessControlServer&acsRequest=METHOD",
        "method":"POST",
        "parameters":[
          {
            "name":"threeDSMethodData",
            "value":"eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN0Lm9wcHdhLmNvbS9jb25uZWN0b3JzL2FyX3NpbXVsYXRvci8zZHMyO2pzZXNzaW9uaWQ9QUY0Nzk1MjBFRDY0QzIzN0JFNDJERjg5NThEMTYyQjAudWF0MDEtdm0tY29uMDM_YXN5bmNzb3VyY2U9QUNJXzNEU18yJnR5cGU9bWV0aG9kTm90aWZpY2F0aW9uJm5kY2lkPThhYzdhNGM4OTBmYzc0OGIwMTkwZmU2YWQ1NmIwMjQxXzJlOWI1YWQ1Y2I5YTQyMWVhZmRhNmMxMjMxMTlkYTI3IiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiIxODlhMzk0Yy00MmY5LTQ0MDEtOTc1Zi1iYzcxM2U2NzE2NWYifQ"
          }
        ]
      }
    ]
  },
  "risk":{
    "score":"0"
  },
  "buildNumber":"58e6de7e1e6a0b42807a3a291ebd50fa46ba3ff9@2024-08-19 00:42:32 +0000",
  "timestamp":"2024-08-19 13:46:04+0000",
  "ndc":"8ac7a4c890fc748b0190fe6ad56b0241_2e9b5ad5cb9a421eafda6c123119da27",
  "source":"OPP",
  "paymentMethod":"CC",
  "shortId":"4476.6608.6311"
}

Get the id of the payment so you can use it later to get the payment status.

And get the redirect data for processing the 3DS verification.

📘

Gateway documentation

For the gateway documentation and playground for this request go to Gateway documentation for server to server and in the Use cases section select Synchronous payment.

We add the 3DS parameters to the payment request as shown above. But the gateway documentation and playground for 3DS verification is at Gateway documentation for standalone 3DS.


2. Handle the 3DS redirect

To perform the 3DS verification, get the redirect to perform the 3DS verification from the redirect attribute of the above response. For example.

Handle 3DS redirect

  "redirect":{
    "url":"https://test.oppwa.com/connectors/asyncresponse_simulator;jsessionid=AF479520ED64C237BE42DF8958D162B0.uat01-vm-con03?asyncsource=ACI_3DS_2&type=methodRedirect&cdkForward=true&ndcid=8ac7a4c890fc748b0190fe6ad56b0241_2e9b5ad5cb9a421eafda6c123119da27",
    "parameters":[  
    ],
    "preconditions":[
      {
        "origin":"iframe#hidden",
        "waitUntil":"iframe#load",
        "description":"Hidden iframe post for 3D Secure 2.0",
        "url":"https://test.ppipe.net/connectors/demo/submit?action=ACI3DS2AccessControlServer&acsRequest=METHOD",
        "method":"POST",
        "parameters":[
          {
            "name":"threeDSMethodData",
            "value":"eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly90ZXN0Lm9wcHdhLmNvbS9jb25uZWN0b3JzL2FyX3NpbXVsYXRvci8zZHMyO2pzZXNzaW9uaWQ9QUY0Nzk1MjBFRDY0QzIzN0JFNDJERjg5NThEMTYyQjAudWF0MDEtdm0tY29uMDM_YXN5bmNzb3VyY2U9QUNJXzNEU18yJnR5cGU9bWV0aG9kTm90aWZpY2F0aW9uJm5kY2lkPThhYzdhNGM4OTBmYzc0OGIwMTkwZmU2YWQ1NmIwMjQxXzJlOWI1YWQ1Y2I5YTQyMWVhZmRhNmMxMjMxMTlkYTI3IiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiIxODlhMzk0Yy00MmY5LTQ0MDEtOTc1Zi1iYzcxM2U2NzE2NWYifQ"
          }
        ]
      }
    ]
  },

To perform the 3DS redirect, do these steps:

  1. From the redirect attribute
    1. Get the preconditions.url and the preconditions.parameters array, which can have multiple key value pairs with name and value attributes.
    2. Get the url and parameters array from the redirect object
  2. Open a hidden iframe and make a POST request to the preconditions url in the following format.
    <form name='downloadForm' action='preconditions.url' method='POST'>
        <INPUT type='hidden' name='preconditions.parameters[].name' value='preconditions.parameters[].value'>
    </form>
    <script>
        window.onload = submitForm;
        function submitForm() { downloadForm.submit(); }
    </script>
  3. Create another iframe where the cardholder will see the authentication request from their bank.
    <form name='downloadForm' action='redirect.URL' method='POST'>
        <INPUT type='hidden' name='redirect.parameters[].name' value='redirect.parameters[].value'>
    </form>
    <script>
        window.onload = submitForm;
        function submitForm() { downloadForm.submit(); }
    </script>
    1. Add the key/value pairs from the redirect.parameters[] array.
    2. Use a separate page so that the issuer authentication page always displays correctly.
  4. Listen and wait for the onLoad() event from the preconditions step, then redirect the shopper within the iframe to the redirect.url.

The gateway documentation and playground for this step is at Gateway documentation for standalone 3DS under 2. How to handle the responses, but we are not using standalone 3DS.


3. Get the payment status

Get the payment result from the payments endpoint using a request in this format.

curl -G https://eu-test.oppwa.com/v1/payments/{id} \
 -d "entityId={channelId}" \
 -H "Authorization: Bearer {auth_token}"

The gateway documentation and playground for this step is at Gateway documentation for asynchronous payments under 3. Get the payment status.

After the user performs the 3DS verification step, the user is redirected to the shopperResultUrl, and you can display the result of the payment there.


4. Check the payment response

Here are examples of the payment response for an account funding transaction.

{
  "id":"8ac7a4a1917803de01917aa40667038e",
  "paymentType":"PA",
  "paymentBrand":"VISA",
  "amount":"20.00",
  "currency":"EUR",
  "descriptor":"1101.0873.7831 ECOMChannel ",
  "merchantTransactionId":"P223",
  "result":{
    "avsResponse":"U",
    "cvvResponse":"P",
    "code":"000.100.112",
    "description":"Request successfully processed in 'Merchant in Connector Test Mode'"
  },
  "resultDetails":{
    "ExtendedDescription":"Approved",
    "clearingInstituteName":"SecureTrading Omnipay Demo",
    "ConnectorTxID1":"385390|U|true|VU        P||0822|331|Y|A |RECURRING|80||false|false|false|812|",
    "TxIdentifier":"822161055567902",
    "ConnectorTxID3":"423503385390|00|0170282216105556790200423A ||1||0822151055||||||||||||||",
    "connectorId":"423503385390",
    "ConnectorTxID2":"320983|822161055567902",
    "AcquirerResponse":"00",
    "reconciliationId":"1101.0873.7831",
    "merchantAccountId":"8ac7a4c890fc748b0190fe70998c0248",
    "SchemeResponseCode":"00"
  },
  "card":{
    "bin":"420000",
    "last4Digits":"0042",
    "holder":"Joe Smith",
    "expiryMonth":"05",
    "expiryYear":"2030"
  },
  "customer":{
    "givenName":"Joe",
    "surname":"Smith",
    "merchantCustomerId":"CUST11",
    "phone":"34667666666",
    "email":"[email protected]",
    "ip":"2001:8a0:7f4b:1b00:dd4e:2bf6:1fb8:56af"
  },
  "billing":{
    "street1":"Calle Principal 123",
    "city":"Barcelona",
    "postcode":"08123",
    "country":"ES"
  },
  "threeDSecure":{
    "eci":"05",
    "verificationId":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",
    "version":"2.2.0",
    "dsTransactionId":"433ec799-d9db-49a6-9cdf-900acdbc79f2",
    "acsTransactionId":"fe3e7124-ec18-449b-b99e-6df46d18561a",
    "flow":"challenge",
    "authenticationStatus":"Y"
  },
  "risk":{
    "score":"0"
  },
  "buildNumber":"58e6de7e1e6a0b42807a3a291ebd50fa46ba3ff9@2024-08-19 00:42:32 +0000",
  "timestamp":"2024-08-22 15:10:55+0000",
  "ndc":"8ac7a4c890fc748b0190fe6ad56b0241_b5f3815268964e18a4f4ce9fb363e8c5",
  "source":"OPP",
  "paymentMethod":"CC",
  "shortId":"1101.0873.7831"
}

The above transactions were approved, as shown in this section. In a production environment, an approved transaction will have a result code of 000.000.000.

  "result":{
    "avsResponse":"U",
    "cvvResponse":"P",
    "code":"000.100.112",
    "description":"Request successfully processed in 'Merchant in Connector Test Mode'"
  },

If the transaction is declined, the result code will not be 000.000.000. For more details, see Transaction results.

If you are processing a recurring payment, the response should also contain the standingInstruction details.


5. Manage the payment

From the response for an approved payment, get the value of the payment id. You can use the id to manage the payment. You can capture a preauthorisation, refund a payment, or reverse a preauthorisation with the Backoffice API. See Backoffice API operations. You can also do the back office operations in the UI of Connect by CardCorp.


6. Process recurring payments

To process recurring payments, from the initial payment response also get the CardholderInitiatedTransactionID. See Repeated payment.

If you are creating a one-click checkout by saving the card in the payment gateway, also get the registrationId and the 3D secure data to create a repeated payment.