# Cards

## Creating a Virtual Card

**Pocket ID** and a single-use **4096 bit RSA** key pair (private and public
key) in [PKCS#1](https://datatracker.ietf.org/doc/html/rfc8017) or
[PKCS#1.5](https://datatracker.ietf.org/doc/html/rfc8017) format is required in
order to create a virtual card. The RSA key pair should be discarded after use,
and should originate from the client's device. These key pairs are monitored for
duplicates.

Pocket ID can be retrieved by following the steps
[here](/products/partner-api/guides/building/pockets).

The public key will be used to encrypt sensitive information of the card (i.e.
CVV, PAN, and expiration date) which will be included in the response. Response
will return **card_id, encrypted_cvv, encrypted_pan, and encrypted_expiration.**
The encrypted data can then be decrypted using the private key.


```bash
public_key="public_key.pem"
private_key="private_key.pem"
openssl genrsa -out $private_key 4096
openssl rsa -in $private_key -pubout -out $public_key


body=$(jq --null-input -c -r --arg public_key_body "$(<public_key.pem)" '{public_key: $public_key_body}')
response=$(send_jiko_request "POST" "/api/v1/jiko-accounts/$account_id/virtual-cards/" $body);


fields=("pan" "cvv" "expiration")
for field in "${fields[@]}"; do
   echo $response | jq -r ".encrypted_$field" | base64 -d > .temp_encrypted_data
   echo $field = $(openssl rsautl -decrypt -inkey private_key.pem -in .temp_encrypted_data)
done


rm .temp_encrypted_data $public_key $private_key
```

## Getting Virtual Card Information

Similar to creating a virtual card, **Account ID** and a single-use **4096 bit
RSA** key pair in [PKCS#1](https://datatracker.ietf.org/doc/html/rfc8017) or
[PKCS#1.5](https://datatracker.ietf.org/doc/html/rfc8017) format is required
apart from the card_id.

Please note that the request method will be **POST** since the **public_key**
must be included in the request body.


```bash
public_key="public_key.pem"
private_key="private_key.pem"
openssl genrsa -out $private_key 4096
openssl rsa -in $private_key -pubout -out $public_key


body=$(jq --null-input -c -r --arg public_key_body "$(<public_key.pem)" '{public_key: $public_key_body}')
response=$(send_jiko_request "POST" "/api/v1/jiko-accounts/$account_id/virtual-cards/$card_id/" $body);


fields=("pan" "cvv" "expiration")
for field in "${fields[@]}"; do
   echo $response | jq -r ".encrypted_$field" | base64 -d > .temp_encrypted_data
   echo $field = $(openssl rsautl -decrypt -inkey private_key.pem -in .temp_encrypted_data)
done


rm .temp_encrypted_data $public_key $private_key
```

## Ordering a Physical Card

To order a physical card, a card order must be created. Like applications, card
orders have statuses. The statuses are as follows:

| Status | Description |
|  --- | --- |
| `INITIAL` | A new card order starts out in this state. |
| `CARD_CREATED` | The card order has been partially processed and now contains a card_id that can be used to set PIN, close the card and more. This state is very short-lived. |
| `ORDERED` | The physical card has been ordered and will be delivered to the given address. |
| `RECEIVED` | Once the PIN has been set by the end user, the card will be considered received. The card itself also has a status, `NOT_ACTIVATED`, that will be updated when the PIN is set. |


In production, card orders are batch processed periodically, and will stay in
the INITIAL state until processing starts. In the sandbox environment, each card
order can be selectively processed by calling
[Generate Physical Card From Order](/products/partner-api/reference/sandbox/generate_physical_card_from_order_api_v1_sandbox_generate_card__post).

To create a card order, call
[Create Physical Card Order](/products/partner-api/reference/physical-cards/create_physical_card_order_api_v1_jiko_accounts__account_id__card_orders__post):


```bash
body='{
  "name_on_card": "Jiko Customer",
  "shipping_address": {
    "street_address": "2000 Allston Way",
    "city": "Berkeley",
    "postal_code": "94701",
    "state": "CA",
    "country": "USA"
  }
}';
send_jiko_request "POST" "/api/v1/jiko-accounts/$account_id/card-orders/" $body);
```

In the sandbox, you can force the card order by extracting the card order id and
calling POST:


```bash
card_order_id="id-from-response"
body='{
 "card_order_id": "'$card_order_id'"
}'
send_jiko_request "POST" "/api/v1/sandbox/generate-card/" $body);
```

After the card order is processed, a PIN must be set. Preferably, this happens
once the end user has received their card, but can be done as soon as
CARD_CREATED status is reached. Only once the PIN has been set will the user be
able to swipe, dip, lock and open the card.

## Setting the PIN

PIN is required to be encrypted at the client device before sending a request to
the partner API service. Encryption should be done using the public key provided
via Jiko Partner API.

Obtain available public keys:


```bash
endpoint="/api/v1/public_keys/";
curl --request GET --url https://$PREFIX.sandbox-api.jikoservices.com$endpoint
```

The response should return a public key in **set_pin** field. Encrypt the 4
digit pin using the public key in **set_pin** (4096-bit RSA with padding) and
encode in base64.


```bash
curl --request GET \
 --url https://$PREFIX.sandbox-api.jikoservices.com/api/v1/public_keys/ | jq -r '.set_pin' > set_pin.pub
pin="1234"
encrypted_pin=$(echo $pin | openssl rsautl -encrypt -pubin -inkey set_pin.pub  | base64)
endpoint="/api/v1/jiko-accounts/$account_id/cards/$card_id/pin";
body='{
 "encrypted_pin": "'$encrypted_pin'"
}'
send_jiko_request "POST" "/api/v1/jiko-accounts/$account_id/cards/$card_id/pin" $body
```