Universal card storage feature allows merchants to get payments from their customer's saved cards.
1- To get the necessary information, you need to send email and gsmNumber information to this service. In the response, you can understand if your customer has a saved card or not. This service returns you a response including scriptType tag. You can see scriptType values below,
2- If your customer has a stored card(scriptType:CONSUMER_WITH_CARD_EXIST), please follow the steps below
Script parameter in the response of UCS service should be printed in the webpage. This javascript loads related items for payments without card information.
"<script type=\"text/javascript\">if (typeof iyziUcsInit == 'undefined') {var iyziUcsInit = {\"baseUrl\":\"https://sandbox-api.iyzipay.com\", \"buyerProtectedConsumer\":false,\"ucsToken\":\"3f971db9-897c-4c74-aa29-ed9b40644b12\",\"scriptType\":\"CONSUMER_WITH_CARD_EXIST\",\"buyerProtectedMerchant\":false,\"maskedGsmNumber\":\"+90********31\",\"gsmNumber\":\"+905557378631\",\"merchantName\":\"Sandbox Merchant Name - 58892\", createTag: function () {var iyziUcsJSTag = document.createElement('script'); iyziUcsJSTag.setAttribute('src', 'https://sandbox-static.iyzipay.com/checkoutform/v2/bundle.js?v=1575919444317'); document.head.appendChild(iyziUcsJSTag);}};if (typeof iyziInit == 'undefined') { iyziUcsInit.createTag(); }}</script>"
In your checkout form, put this div line to the related place
<div id="ucs-cards"></div>
After you print the javascript and the div above, your website will load the screen below into the ucs-cards div. If your customer continues the process, he/she will be asked to make an OTP-SMS to access the stored cards.
At this step, your web page also loads a javascript object called universalCardStorage. You can find detailed information about this object in next steps.
After your customer passes the OTP, the screen is updated as below and it shows the saved cards of your customer.
You can think this page as a form. You can put a button to a related area and whenever your customer clicks the button, you can check the values of universalCardStorage object. The payment flow can be processed according to values in universalCardStorage.
universalCardStorage: This javascript object is loaded as soon as you called the UCS service. To be able to follow all process you can check this object if any action has been taken on your payment form. It has 4 parameters. If your customer already has stored cards, registerConsumerCard parameter will be True. Otherwise, by default registerConsumerCard parameter will be false.
If your customer already has a saved card, there are 3 conditions that you may follow
Your customer has a saved card but did not pass the OTP - sms verification (This means the customer did not see his/hre saved cards yet.)
universalCardStorage: {registerConsumerCard: true, gsmNumber: "+905557378631", consumerToken: undefined, cardToken: undefined}
If your form is submitted at this step, you can understand that your customer does not want to use a sotred card. You can check the object universalCardStorage. You can see that consumerToken and cardToken values in this object are undefined. So please process the payment with the form that you already use.
The customer has a saved card and passed the OTP SMS verification (Customer sees the list of cards in the next screen )
universalCardStorage: {registerConsumerCard: true, gsmNumber: "+905557378631", consumerToken: "31ad9-2335a3b", cardToken: "ca9c8360-ca08"}
In this case, if customer submits the form, consumerToken and cardToken values are defined in universalCardStorage object. You can pass these values to your backend and use them in a payment request. This will provide you to get payments from saved cards. Instead of sending card information, passing consumerToken, cardToken and ucsToken information will be enough to use a saved card.(ucsToken value is available in UCS init response).
{registerConsumerCard: true, gsmNumber: "+905557378631", consumerToken: "31ad9-2335a3b", cardToken: undefined}
If the value of scriptType parameter in UCS service response is UCS_CONSENT then you can understand that your customer does not have a saved card in iyzico ecosystem. At the same time registerConsumerCard parameter in the universalCardStorage object will be received as False. At this step, if you want to save the card, you need to give information about aggreements and the customer should accept the aggreement. To do this, adding below "div" will be enough to show the agreement and informative text provided by iyzico.
You should also print javascript code coming from "script" parameter
Put mentioned "div" to the related area of your payment form
<div id="ucs-cards"></div>
Your customer will see the screen below. If your customer checks the checkbox, registerConsumerCard parameter in universalCardStorage javascript object will become True. So as soon as your payment form is submitted, you can check this javascript value(universalCardStorage.registerConsumerCard). If it is True, this means that your customer confirmed the aggrement. So the card can be saved at the time of payment.
.
Not: Every UCSToken and universalCardStorage object is valid for 30 minutes. If they are not used within 30 minutes. you need to reinitate the UCS init request.
**Parameters to be sent to the service are as follows:
UCS init service**
Parameter | Type | Mandatory | Description |
---|---|---|---|
locale | string | no | Language (default: tr) |
conversationId | string | no | If set, conversation ID to match request and response |
string | yes | Email address of card owner | |
gsmNumber | string | yes | Gsm number of card owner |
Parameters to be returned from the service are as follows:
Parametre ismi | Tip | Açıklama |
---|---|---|
status | string | Service response result (success / failure) |
script | string | Javascript code for retrieving the stored cards. It should be printed in the web page |
scriptType | string | Specifies whether the customer has stored card or not . It can be CONSUMER_WITH_CARD_EXIST and UCS_CONSENT |
merchantName | string | Merchant name. |
maskedGsmNumber | string | Masked gsm number of customer |
gsmNumber | string | Customer's gsm number |
buyerProtectedConsumer | boolean | if customer has protected payments, it can be learnt from this tag |
buyerProtectedMerchant | boolean | if protected payment is activated for the merchant, this value becomes true |
errorCode | string | Error code if service response status is failure |
errorMessage | string | Error message if service response status is failure |
errorGroup | string | Error group if service response status is failure |
locale | string | Language (default: tr) |
systemTime | integer | Response system timestamp value |
conversationId | string | If set, conversation ID to match request and response |
// create request class
$request = new \Iyzipay\Request\UCSInitializeRequest();
$request->setConversationId("1234566");
$request->setLocale("tr");
$request->setEmail("email@iyzico.com");
$request->setGsmNumber("+905557378631");
// make request
$result = \Iyzipay\Model\UCSInitialize::create($request,Config::options());
//Request
{
"locale": "tr",
"conversationId": "123456",
"email": "email@iyzico.com",
"gsmNumber": "+905557378631"
}
//Response
{
"buyerProtectedConsumer": false,
"buyerProtectedMerchant": false,
"gsmNumber": "+905533378631",
"locale": "tr",
"maskedGsmNumber": "+90********31",
"merchantName": "Test Name - 58892",
"script": "<script type=\"text/javascript\">if (typeof iyziUcsInit == 'undefined') {var iyziUcsInit = {\"baseUrl\":\"https://sandbox-api.iyzipay.com\", \"ucsToken\":\"32b30114-85dd-47a5-a2bd-9071c95bc389\",\"scriptType\":\"UCS_CONSENT\",\"buyerProtectedMerchant\":false,\"maskedGsmNumber\":\"+90********31\",\"gsmNumber\":\"+905533378631\",\"merchantName\":\"Sandbox Merchant Name - 58892\", createTag: function () {var iyziUcsJSTag = document.createElement('script'); iyziUcsJSTag.setAttribute('src', 'https://sandbox-static.iyzipay.com/checkoutform/v2/bundle.js?v=1575969451615'); document.head.appendChild(iyziUcsJSTag);}};if (typeof iyziInit == 'undefined') { iyziUcsInit.createTag(); }}</script>",
"scriptType": "UCS_CONSENT",
"status": "success",
"systemTime": 1575969451615,
"ucsToken": "32b30114-a2bd-9071c95bc389"
}
Sameple Codes
Parameters to be sent to the service are as follows:
Input Name | Type | Mandatory | Description |
---|---|---|---|
price | Decimal | Yes | Total amount of basket. The sum of basket items’ amount must be equal to the price of basket |
paidPrice | Decimal | Yes | Final amount (including installment fee) that will be charged to customer’s card |
currency | String | Yes | Currency (default: TRY). Alternatively, you can set USD, EUR, GBP and IRR |
installment | Integer | Yes | Installment value. For single installment payments it should be 1 (valid values: 1, 2, 3, 6, 9, 12) |
cardToken | String | Yes | Card Token received from UCS service. It can be accessed from universalCardStorage object |
consumerToken | String | Yes | Consumer Token received from UCS service. It can be accessed from universalCardStorage object |
ucsToken | String | Yes | UCS Token received from UCS service. It can be accessed from UCS init response |
id(Buyer) | String | Yes | ID of buyer. |
name(Buyer) | String | Yes | Name of buyer |
surname(Buyer) | String | Yes | Surname of buyer |
identityNumber(Buyer) | String | Yes | Identity number of buyer. TCKN for Turkish merchants, passport number for foreign merchants |
city(Buyer) | String | Yes | City of buyer |
country(Buyer) | String | Yes | Country of buyer |
email(Buyer) | String | Yes | Email of buyer |
ip(Buyer) | String | Yes | IP of buyer |
registrationAddress(Buyer) | String | Yes | Registration address of buyer |
contactName(BillingAddress) | String | Yes | Contact name of billing address |
city(BillingAddress) | String | Yes | City name of billing address |
country(BillingAddress) | String | Yes | Country name of billing address |
address(BillingAddress) | String | Yes | Address details of billing address |
contactName(ShippingAddress) | String | Yes | Contact name of shipping adress. If one of the itemType in basket is PHYSICAL, then this parameter will be mandatory |
city(ShippingAddress) | String | Yes | City name of shipping address. If one of the itemType in basket is PHYSICAL, then this parameter will be mandatory |
country(ShippingAddress) | String | Yes | Country name of shipping address. If one of the itemType in basket is PHYSICAL, then this parameter will be mandatory |
address(ShippingAddress) | String | Yes | Address details of shipping address. If one of the itemType in basket is PHYSICAL, then this parameter will be mandatory |
id(BasketItems) | String | Yes | Basket Item ID |
itemType(BasketItems) | String | Yes | Item Type. Valid values are PHYSICAL,VIRTUAL |
price(BasketItems) | Decimal | Yes | Price value for each item. Must be greater than zero |
name(BasketItems) | String | Yes | Name of the item in the basket |
category1(BasketItems) | String | Yes | Category 1 for item in the basket |
zipCode(Buyer) | String | No | Zip code of buyer |
zipCode(ShippingAddress) | String | No | Zip code of shipping address |
zipCode(BillingAddress) | String | No | Zip code of billing address |
category2(BasketItems) | String | No | Category 2 for item in the basket |
gsmNumber(Buyer) | String | No | GSM number of buyer |
subMerchantPrice(BasketItem) | Decimal | No | Payout amount to subMerchant of each item. Must be greater than zero. Mandatory value for marketplace solution |
subMerchantKey(BasketItem) | String | No | Submerchant ID value. Mandatory value for marketplace solution |
registerCard | Integer | No | Parameter that shows card details will store or not. Default value is 0 and valid values are 0 or 1 |
cardAlias | Integer | No | If registerCard value is 1 cardAlias can send within request. |
registrationDate(Buyer) | String | No | Registration date of buyer. Format should be “2015-09-17 23:45:06” |
lastLoginDate(Buyer) | String | No | Last login date of buyer. Format should be “2015-09-17 23:45:06” |
locale | String | No | Language (default: tr) |
conversationId | String | No | Conversation ID to match request and response |
basketId | String | No | Merchant's basket ID |
paymentChannel | String | No | Payment channel. Valid values are WEB, MOBILE, MOBILE_WEB, MOBILE_IOS, MOBILE_ANDROID, MOBILE_WINDOWS, MOBILE_TABLET, MOBILE_PHONE |
paymentGroup | String | No | Payment group (default: PRODUCT). Valid values are PRODUCT, LISTING, SUBSCRIPTION |
paymentSource | String | No | Payment source. Valid values are SHOPIFY, MAGENTO, PRESTASHOP, WOOCOMMERCE, OPENCART |
Parameters to be returned from the service are as follows:
Output Name | Type | Description |
---|---|---|
status | String | Service response result (success / failure) |
errorCode | String | Error code if service response status is failure |
errorMessage | String | Error message if service response status is failure |
errorGroup | String | Error group if service response status is failure |
locale | String | Language (default: tr) |
systemTime | Long | Response system timestamp value |
conversationId | String | If set, conversation ID to match request and response |
paymentId | String | ID of the payment. Merchants should keep payment ID in their system (this ID will be used for cancel requests) |
price | Decimal | Total amount of basket. The sum of basket items’ amount must be equal to the price of basket |
paidPrice | Decimal | Final amount (including installment fee) that will be charged to customer’s card. Merchants should store this value in their system |
currency | String | Currency of request |
installment | Integer | Installment number of payment, for single payments it returns 1. Valid values are 1, 2, 3, 6, 9, 12 |
basketId | String | Merchant's basket ID |
binNumber | String | First 6 digit of card |
cardAssociation | String | Valid values are VISA, MASTER_CARD, AMERICAN_EXPRESS, TROY |
cardFamily | String | Valid values are Bonus, Axess, World, Maximum, Paraf, CardFinans, Advantage |
cardType | String | Valid values are CREDIT_CARD, DEBIT_CARD, PREPAID_CARD |
fraudStatus | Integer | Fraud risk status for payment request (0 for review / 1 for accept) |
iyziCommissionFee | Decimal | iyzico commission fee for payment transaction |
iyziCommissionRateAmount | Decimal | iyzico commission rate amount for payment transaction |
merchantCommissionRate | Decimal | Merchant commission rate (e.g. price=100 & paidPrice=110, then merchant commission rate = 10) |
merchantCommissionRateAmount | Decimal | Merchant commission rate amount (e.g. price=100 & paidPrice=110, then merchant commission rate amount = 10) |
paymentTransactionId (ItemTransactions) | String | ID of basket item. Merchants should keep payment ID in their system (this ID will be used for cancel requests) |
itemId(ItemTransactions) | String | Item ID of each item in basket |
price(ItemTransactions) | Decimal | Item price of each item in basket |
paidPrice(ItemTransactions) | Decimal | Captured amount from card based on each item. Merchants should keep paidPrice in their system |
transactionStatus (ItemTransactions) | Integer | Status of a payment transaction. (0 for waiting / -1 for rejected by fraud / 1 for waiting for approval / 2 for approved |
blockageRate(ItemTransactions) | Decimal | Blockage rate based on each item. |
blockageRateAmountMerchant(ItemTransactions) | Decimal | Blockage rate amount for merchant based on each item |
blockageResolvedDate(ItemTransactions) | String | Blockage resolve date based on each item. Date format should be “2015-10-19 14:36:52” |
iyziCommissionFee(ItemTransactions) | Decimal | iyzico commission fee based on each item |
iyziCommissionRateAmount(ItemTransactions) | Decimal | iyzico commission rate amount based on each item |
merchantCommissionRate(ItemTransactions) | Decimal | Merchant commission rate (e.g. price=100 & paidPrice=110, then merchant commission rate = 10) |
merchantCommissionRateAmount(ItemTransactions) | Decimal | Merchant commission rate amount (e.g. price=100 & paidPrice=110, then merchant commission rate amount = 10) |
merchantPayoutAmount(ItemTransactions) | Decimal | Payout amount for each item transaction. This is the amount that remains after after substracting iyzicoCommissionRateAmount, iyzicoCommissionFee and blockageRateAmountMerchant from paidPrice(ItemTransactions) |
paidPrice(ItemTransactions)(convertedPayout) | Decimal | Converted charged amount to card based on each item. Merchants should keep paidPrice in their system. |
iyziCommissionFee(ItemTransactions)(convertedPayout) | Decimal | Converted iyzico commission fee based on each item |
iyziCommissionRateAmount(ItemTransactions)(convertedPayout) | Decimal | Converted iyzico commission rate amount based on each item |
blockageRateAmountMerchant(ItemTransactions)(convertedPayout) | Decimal | Converted blockage rate amount for merchant based on each item |
merchantPayoutAmount(ItemTransactions)(convertedPayout) | Decimal | Converted payout amount for each item transaction. This the amount that remains after substracting iyzicoCommissionRateAmount, iyzicoCommissionFee and blockageRateAmountMerchant from paidPrice(ItemTransactions) |
iyziConversationRate(ItemTransactions)(convertedPayout) | Decimal | iyzico conversation rate |
iyziConversationRateAmount(ItemTransactions)(convertedPayout) | Decimal | iyzico conversation rate amount |
currency(ItemTransactions)(convertedPayout) | String | Currency for payout conversion |
$request = new \Iyzipay\Request\CreatePaymentRequest();
$request->setLocale(\Iyzipay\Model\Locale::TR);
$request->setConversationId("123456789");
$request->setPrice("1");
$request->setPaidPrice("1.2");
$request->setCurrency(\Iyzipay\Model\Currency::TL);
$request->setInstallment(1);
$request->setBasketId("B67832");
$request->setPaymentChannel(\Iyzipay\Model\PaymentChannel::WEB);
$request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
$paymentCard = new \Iyzipay\Model\PaymentCard();
$paymentCard->setUcsToken("sampleToken");
$paymentCard->setConsumerToken("55287-9000-00000-08");
$paymentCard->setCardToken("12332-3523-345-234-56456");
$request->setPaymentCard($paymentCard);
$buyer = new \Iyzipay\Model\Buyer();
$buyer->setId("BY789");
$buyer->setName("John");
$buyer->setSurname("Doe");
$buyer->setGsmNumber("+905350000000");
$buyer->setEmail("email@email.com");
$buyer->setIdentityNumber("74300864791");
$buyer->setLastLoginDate("2015-10-05 12:43:35");
$buyer->setRegistrationDate("2013-04-21 15:12:09");
$buyer->setRegistrationAddress("Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1");
$buyer->setIp("85.34.78.112");
$buyer->setCity("Istanbul");
$buyer->setCountry("Turkey");
$buyer->setZipCode("34732");
$request->setBuyer($buyer);
$shippingAddress = new \Iyzipay\Model\Address();
$shippingAddress->setContactName("Jane Doe");
$shippingAddress->setCity("Istanbul");
$shippingAddress->setCountry("Turkey");
$shippingAddress->setAddress("Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1");
$shippingAddress->setZipCode("34742");
$request->setShippingAddress($shippingAddress);
$billingAddress = new \Iyzipay\Model\Address();
$billingAddress->setContactName("Jane Doe");
$billingAddress->setCity("Istanbul");
$billingAddress->setCountry("Turkey");
$billingAddress->setAddress("Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1");
$billingAddress->setZipCode("34742");
$request->setBillingAddress($billingAddress);
$basketItems = array();
$firstBasketItem = new \Iyzipay\Model\BasketItem();
$firstBasketItem->setId("BI101");
$firstBasketItem->setName("Binocular");
$firstBasketItem->setCategory1("Collectibles");
$firstBasketItem->setCategory2("Accessories");
$firstBasketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
$firstBasketItem->setPrice("0.3");
$basketItems[0] = $firstBasketItem;
$secondBasketItem = new \Iyzipay\Model\BasketItem();
$secondBasketItem->setId("BI102");
$secondBasketItem->setName("Game code");
$secondBasketItem->setCategory1("Game");
$secondBasketItem->setCategory2("Online Game Items");
$secondBasketItem->setItemType(\Iyzipay\Model\BasketItemType::VIRTUAL);
$secondBasketItem->setPrice("0.5");
$basketItems[1] = $secondBasketItem;
$thirdBasketItem = new \Iyzipay\Model\BasketItem();
$thirdBasketItem->setId("BI103");
$thirdBasketItem->setName("Usb");
$thirdBasketItem->setCategory1("Electronics");
$thirdBasketItem->setCategory2("Usb / Cable");
$thirdBasketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
$thirdBasketItem->setPrice("0.2");
$basketItems[2] = $thirdBasketItem;
$request->setBasketItems($basketItems);
$payment = \Iyzipay\Model\Payment::create($request, Config::options());