Stored Cards

982 مشاهدات Markdown

The three endpoints that read a client's stored cards, pick the default and delete one.

Overview

A stored card is a card held at the client's payment provider. WISECP does not keep the card number; it holds a token from the provider and enough to recognise the card — the last four digits, the brand, the expiry.

That is why there is no endpoint here that adds a card. A card is stored on the provider's own screen while the client pays; the API only reads what exists, moves the default and deletes.

Reference

Listing Cards

get/api/v1/admin/clients/{id}/cards
Clients/GetClientCards admin

Returns the client's stored cards. The card number never comes back; only the last four digits show.

Response fields data[] — 6
idintId of the stored card.
last4stringThe last four digits of the card number.
brandstringCard brand, for example visa or mastercard.
modulestringThe payment module holding the card, for example Stripe.
is_defaultboolWhether this is the default card.
expirystringExpiry date, in 12/27 form.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/clients/42/cards' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();

const primary = body.data.find((card) => card.is_default);
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->GetClientCards(['id' => 42]);

foreach ($response['data'] as $card) {
    if ($card['is_default']) {
        $primary = $card;
    }
}
Response
{
  "data": [
    {
      "id": 88,
      "last4": "4242",
      "brand": "visa",
      "module": "Stripe",
      "is_default": true,
      "expiry": "12/27"
    }
  ]
}

Setting the Default Card

put/api/v1/admin/clients/{id}/cards/{card_id}/default
Clients/SetClientCardDefault admin

Makes a card the default. The flag on the previous one clears by itself.

Body —
——No body is needed; send an empty one. Both the client and the card come from the path.
——There is no way to clear the default without another card taking its place.
Response fields data — 2
card_idintId of the card that became the default.
defaultboolAlways true.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/clients/42/cards/88/default' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards/88/default', {
  method: 'PUT',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards/88/default');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->SetClientCardDefault([
    'id'      => 42,
    'card_id' => 88,
]);

Deleting a Card

delete/api/v1/admin/clients/{id}/cards/{card_id}
Clients/DeleteClientCard admin may move the default

Deletes the stored card. If it was the default, another one takes its place and the id comes back in the response. The provider is asked to delete its copy too. The card leaves the client either way; the provider's answer comes back in gateway_removal.

Response fields data — 5
deletedboolWhether the delete succeeded.
card_idintId of the deleted card.
new_default_idintId of the new default card. 0 when the deleted card was not the default.
gateway_removalstringWhat the provider did with its copy: removed · failed (refused or unreachable; remove it from the provider's panel) · unsupported (the payment module cannot delete stored cards) · none (no payment module on the card).
gateway_errorstringThe provider's message. Present only when gateway_removal is failed and the provider returned one.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/42/cards/88' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards/88', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();

if (body.data.new_default_id) {
  // The default moved to another card.
}
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards/88');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->DeleteClientCard([
    'id'      => 42,
    'card_id' => 88,
]);

$newDefault = $response['data']['new_default_id'] ?? 0;

Pitfalls

There is no endpoint that adds a card

A card can only be stored during the client's payment flow, because the number is entered at the provider. An integration trying to add one through the API is looking for an endpoint that does not exist.

Deleting can move the default

Delete the default card and another takes its place; its id comes back in new_default_id. If you keep the default on your side, read that value and update it.

A deleted card can stay at the provider

The response is 200 even when the provider refuses to delete its copy. Check gateway_removal. On failed the card is gone from WISECP but still stored at the provider. Remove it there by hand.

What you see is not the card number

last4 is only there to recognise the card. The API never returns the card number, the full expiry or the security code on any endpoint.

هل كان هذا مفيدًا؟

شكرًا على ملاحظاتك!

هل ما زلت بحاجة إلى مساعدة؟

فريق الدعم متاح على مدار الساعة لمساعدتك في كل ما لم تجده أعلاه.