PAYMILL Unite is a new set of features dedicated to market-place-like businesses.
With Unite you can
In order to connect with you, merchants have to go through an authorization workflow. This workflow is built on OAuth2. The general approach is as follows:
fee_currency
currency
and billed_at
to the fees
attribute of the transaction response.payment_methods
: replaces currencies and methods.livemode
: is true if the received public_key is the live key.is_active
: is true if the merchant can do live transactions with the mentioned payment_methods
.redirect_uri
and custom_param
to authorization code request.Navigate to our Cockpit and open the My Account: Settings page. In the “App” tab you can register a new application. You can create up to 10 applications in your account. As application's don't depend on the live/test mode of your cockpit, you will see them all in both modes.
The OAuth2 workflow consists of three steps. First you request an authorization from the merchant by redirecting him to PAYMILL. If he grants you the requested permissions, we redirect him back to you together with an authorization code. With this code you can request an access token (which is the same as the api key in our case). After you got the access token, you can execute API calls with it on the merchants account. The access token might be invalidated over time (for security reasons). If this happens you can request a new one without requesting authorization again by using refresh tokens you get together with the access token.
If a access_token is not valid any more you get the following error on API-calls: key_inactive
The following paragraphs describe the technical details for these steps.
To request an authorization code for another merchants account, you’ll have to redirect that merchant to the authorization page on our servers.
The target url for this redirect https://connect.www.paymill.org/authorize
and you need to append a few query parameters to the GET request:
client_id
(required): The App ID which you find on the App tab in your settings.response_type
(required): fixed string set to "code".scope
(required): a space-separated list of permissions you want to request. You get more information about permissions further down.redirect_uri
(optional): if you set this, it is used to redirect the merchant to this uri, instead of the static redirect_uri from your App settings. This enables you to use dynamic uris, e.g. for different servers. If you use this feature it is highly recommended to use the checksum parameter too, as otherwise the service will be vulnerable to diverse attacks.custom_param
(optional): whatever you send in this parameter will just be appended to the redirect uri, when we send the merchant back to you. This can be used together with the static redirect uri to identify the merchant, once he comes back. This string has to be url encoded.checksum
(optional): to verify the correctness of the query string you can add the checksum parameter (see checksum validation).https://connect.www.paymill.org/authorize
?client_id=app_1d70acbf80c8c35ce83680715c06be0d15c06be0d
&scope=transactions_rw refunds_rw
&response_type=code
When the merchant is redirected back to your page, we'll append a few query parameters to the uri you provided when registering your application, depending on the outcome of the request.
If the merchant authorizes your request, the parameter code
, containing your authorization code, is appended.
If an error occurs or if the merchant denies authorization, the parameters error
and error_description
are appended. error
contains an error key, error_description
a descriptive message for that error in english. If you want to react to errors programmatically, always rely on the error key and not on the error_description.
Success response:
https://example.com/?code=16a892ebeb21eb286396a1962796af830cbaa3c4
Error response:
https://example.com/?error=access_denied&error_description=The+user+denied+access+to+your+application
error | error_description |
---|---|
access_denied |
The user denied access to your application |
invalid_request |
Invalid or missing response type |
unsupported_response_type |
authorization code grant type not supported |
invalid_scope |
An unsupported scope was requested |
To verify the correctness of the query string you can add a checksum
parameter
The checksum is generated with HMAC. The used algorithm is sha256 and the hash key is your hash token. It has to be created over the complete query string and has to be added (at the end) to the query string as the parameter checksum afterwards.
Example
Connect URL:
https://connect.www.paymill.org/?client_id=app_1d70acbf80c8c35ce8368ab15c06be0d15c06be0d&scope=transactions_rw refunds_rw&response_type=code
<QUERY_STRING>:
client_id=app_1d70acbf80c8c35ce83680715c06be0d15c06be0d&scope=transactions_rw refunds_rw&response_type=code
Hashing function (example in PHP):
$checksum = hash_hmac('sha256', '<QUERY_STRING>', '<HASH_TOKEN>');
Resulting checksum:
024f9d722cb8a2e9bdcaff3e732d26a2730bea1bdae5db11ad0a1f8af5bd571b
New connect URL with checksum:
https://connect.www.paymill.org/?client_id=app_1d70acbf80c8c35ce83680715c06be0d15c06be0d&scope=transactions_rw refunds_rw&response_type=code&checksum=024f9d722cb8a2e9bdcaff3e732d26a2730bea1bdae5db11ad0a1f8af5bd571b
If you want to use the optional parameters redirect_uri
and/or custom_param
you also need to include them into the query string to have a valid connect URL.
There are 3 different privileges for each PAYMILL API endpoint:
Read
: read all objects from this api endpoint.Write
: write objects to this api endoint, read and edit objects writen by yourself.ReadWrite
: read all objects, write new objects, edit anything.A permission is specified by the name of an api endpoint, like transactions
, followed by an underscore, followed by r
(read), w
(write), or rw
(read and write).
Example: transactions_rw
(read and write transactions), clients_r
(read clients), refunds_w
(create new refunds).
Currently possible endpoints: clients, offers, payments, preauthorizations, refunds, subscriptions, transactions, webhooks.
r
and w
flag automatically. If you request permissions like transactions_r transactions_w
then we will combine this into a single transactions_rw
.
refunds_w
without transaction_w
because you can not refund transactions without being able to write transactions. Which permissions are really needed completely depends on your use case. We also ask you to request only the really necessary permissions for your app. For example in the case of marketplaces it is enough to request the write permissions.
If a merchant authorized your request you are handed an authorization code you can exchange for an access token. The access token as described in OAuth2 is a private api key to your merchants account. The api key is also equipped with the permissions you specified during the authorization request.
In order to create the access token, you have to call the access token endpoint at https://connect.www.paymill.org/token
with a POST request. The request body must contain the request parameters using application/x-www-form-urlencoded
format.
client_id
(required): the application id you created when registering an application.client_secret
(required): the access key as show in your app settings. This is automatically the same value as your private api key / private test api key)grant_type
(required): string set to the fixed value "authorization_code"
code
(required): the authorization code retrieved earlierA successful response contains a private api key to the merchants account plus his public api key and a refresh token. If the private api key is a live key, then the response also includes the currencies and payment methods supported by the merchant. The response is sent as application/json:
{
"access_token": "55727e05094c17ef44649a1710b00d57",
"expires_in": null,
"token_type": "bearer",
"scope": "transactions_rw refunds_rw",
"refresh_token": "07fda540e5283039683f6400651b5eaf",
"merchant_id": "mer_1d70acbf80c8c35ce83680715c06be0d15c06be0d",
"is_active": true,
"methods": ["visa", "mastercard"],
"currencies": ["EUR", "GPB],
"payment_methods": [
{
"type": "visa",
"currency": "EUR",
"acquirer": "wirecard"
},
{
"type": "visa",
"currency": "GBP",
"acquirer": "wirecard"
},
{
"type": "mastercard",
"currency": "EUR",
"acquirer": "wirecard"
}
],
"access_keys": {
"test": {
"public_key": "342070708285cd3d98606d2986cb470f",
"private_key": "4fe2b5ba56ff916eb4e644bad381e62e"
},
"live": {
"public_key": "8175823c16dd0c7b222e9ea0e7352e51",
"private_key": "55727e05094c17ef44649a1710b00d57"
}
},
"livemode": true,
"public_key": "8175823c16dd0c7b222e9ea0e7352e51",
}
access_token
is the private access key for the merchant account. If live access keys are available it's the same as live access key else same test access key.token_type
defines the token type (not important).refresh_token
is the code you need to do refresh token request.merchant_id
is the unique identifier of the connected merchant.is_active
is true
if the merchant can do live transaction with the mentioned payment_methods.payment_methods
may contain a list of active payment methods which are combinations of card type, currency and acquirer:visa
: Visa cardsmastercard
: MasterCard cardsamex
: American Express cardsjcb
: JCB cardsdinersclub
: DinersClub cardscup
: China UnionPay cardselv
: Direct debit (ELV, Germany only).currency
may contain every 3-letter currency code supported by PAYMILL and specified by ISO 4217acquirer
may contain one of our recent acquirer ("acceptance", "wirecard"
) for your payment method configuration.access_keys
contains test and live keys. Live keys are available only if the connected merchant can do live transactions.public_key
is the public key of the merchant. If live access keys are available it's the same as live access key else same test access key.
is_active
is false
and the live section of the access_keys
array is missing. You can always request a new api key by using the refresh token. See Refreshing an access token for details. See Webhooks for applications for details on
activation notifications.
If something went wrong, an error response is returned as follows:
{
"error": "invalid_grant",
"error_description": "Token is no longer valid"
}
Possible errors are ...
error | error_description |
---|---|
invalid_request |
Request is invalid (no POST request). |
unsupported_grant_type |
grant_type parameter not set to authorization_code . |
invalid_grant |
Authorization code is invalid or expired. |
invalid_scope |
The requested privileges are not a subset of the originally requested privileges. |
Whenever requesting an access token (either by providing an authorization code or refresh token) you are given a refresh token along side with the access token. This refresh token can be used to generate a new access token at any time.
Trading a refresh token for an access token works similarly as creating an access token with an authorization code: you POST a few parameters to https://connect.www.paymill.org/token
and receive an access token response as described in Creating the access token.
Possible parameters contain ...
client_id
(required): the application id you created when registering your applicationclient_secret
(required): the access key as show in your app settings. This is automatically the same value as your private api key / private test api key)grant_type
(required): fixed string set to refresh_token
refresh_token
(required): the refresh token as given when the last access token was created.scope
(optional): optional set of privileges for the new access token. Must be a subset of the originally requested privileges. Set to the originally requested privileges if omitted.
The response is identical to the one described in Creating the access token.
If creating a transaction through a merchant's PAYMILL account, you can collect a fee for this transaction by adding the fee_amount
, fee_payment
and optionally the fee_currency
parameter. The fee is specified in the same format as the transaction amount. The fee payment should represent a payment of the merchant which will be billed in order to collect the fee:
curl -XPOST https://api.www.paymill.org/v2/transactions
-d amount=4200
-d token=098f6bcd4621d373cade4e832627b4f6
-d currency=EUR
-d fee_amount=420
-d fee_payment=pay_917018675b21ca03c4fb
-d fee_currency=EUR
-u <ACCESSTOKEN>:
This request will charge an amount of 42.00€ through the merchants account. PAYMILL will collect the default disagio and transaction fee. Your additional fee is drawn from the remaining amount.
fee_amount
relates to the parameter fee_currency
so if fee_currency
equals "USD" and fee_amount
equals "100" we will charge 100 USD cents as a fee even if the transaction is in another currency.fee_currency
is not set, the currency of the transaction is used. This might cause problems, if your account does not support the same currencies as your merchants accounts. Therefore we suggest to always use fee_currency
.The transaction now also contains a list of fee objects:
{
"data": {
"id": "tran_54645bcb98ba7acfe204",
"amount": 4200,
...
"fees": [
{
"type": "application",
"application": "app_1d70acbf80c8c35ce83680715c06be0d15c06be0d",
"payment": "pay_917018675b21ca03c4fb",
"amount": 420,
"currency": "EUR",
"billed_at": null
}
]
}
}
When accessing our API by using an API key from your merchant, all objects which are created are also only available in this merchant account. This is not desirable for payment information as you probably wan't to store it on your own account and use it for transactions on your merchant's accounts.
In order to achieve this, you can use a payment objects and token with all merchants which are connected to your application. This is true for all API endpoints which accept a payment id or token as a POST parameter.
The general approach is as follows (for example with transactions):
payment
parameter, along with client, amount and currency to https://api.www.paymill.org/v2/transactionsThe same process is true for the token
parameter.
payments
endpoint.
There are some special webhook events available for Unite:
app.merchant.activated
: triggered as soon as a connected merchant completed the activation process. Live keys only become valid after this event.app.merchant.deactivated
: triggered if a merchant, which has been activated previously gets deactivated again. This might be triggered together with app.merchant.rejected.app.merchant.rejected
: triggered if a newly connected merchant is rejected during his activation process. Live keys will never become valid if this event occurs.app.merchant.pm.update
: triggered if a merchant payment method has become active or inactive. The message will contain all recently active payment methods and an information which one has changed.app.merchant.app.disabled
: triggered, when a merchant disables an application he previously granted access to his accountapp.merchant.live_requests_allowed
: triggered, when merchant allows live requests for an applicationapp.merchant.live_requests_not_allowed
: triggered, when merchant denies live requests for an applicationThese webhooks can be registered to the application's account and are triggered for every merchant who connects to this application.
app.merchant.activated
and app.merchant.rejected
are only triggered for merchant's which hadn't completed their activation when connecting to your application.
The webhook data contains the user_id
(the parameter merchant in the result
) which was already given to you upon the access token request. This id can be used to match a webhook call to an authorization / connect attempt.
Example:
{
"event":
{
"event_type": "merchant.activated",
"event_resource": {
"merchant": "mer_1d70acbf80c8c35ce83680715c06be0d15c06be0d"
},
"created_at": 1358027174
}
}