Keyple Card Calypso C++ Library 2.2.5.6
Reference Terminal Reader API for C++
CmdCardSvDebitOrUndebit.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
14
15/* Keyple Card Calypso */
16#include "CalypsoCardAdapter.h"
17#include "CalypsoCardClass.h"
23#include "SamUtilAdapter.h"
24
25/* Keyple Core Util */
26#include "ApduUtil.h"
27#include "ByteArrayUtil.h"
28#include "IllegalArgumentException.h"
29#include "IllegalStateException.h"
30#include "System.h"
31
32namespace keyple {
33namespace card {
34namespace calypso {
35
36using namespace keyple::core::util;
37using namespace keyple::core::util::cpp;
38using namespace keyple::core::util::cpp::exception;
39
40const int CmdCardSvDebitOrUndebit::SW_POSTPONED_DATA = 0x6200;
41const std::map<const int, const std::shared_ptr<StatusProperties>>
42 CmdCardSvDebitOrUndebit::STATUS_TABLE = initStatusTable();
43
45 const bool isDebitCommand,
46 const std::shared_ptr<CalypsoCardAdapter> calypsoCard,
47 const int amount,
48 const std::vector<uint8_t>& date,
49 const std::vector<uint8_t>& time,
50 const bool isSessionOpen,
51 const bool isExtendedModeAllowed)
52: AbstractCardCommand(isDebitCommand ? CalypsoCardCommand::SV_DEBIT :
53 CalypsoCardCommand::SV_UNDEBIT,
54 -1,
55 calypsoCard),
56 /* Keeps a copy of these fields until the command is finalized */
57 mIsSessionOpen(isSessionOpen),
58 mIsExtendedModeAllowed(isExtendedModeAllowed)
59{
60 /*
61 * @see Calypso Layer ID 8.02 (200108)
62 * CL-SV-DEBITVAL.1
63 */
64 if (amount < 0 || amount > 32767) {
65
66 throw IllegalArgumentException("Amount is outside allowed boundaries (0 <= amount <= " \
67 "32767)");
68 }
69
70 if (date.empty() || time.empty()) {
71
72 throw IllegalArgumentException("date and time cannot be null");
73 }
74
75 if (date.size() != 2 || time.size() != 2) {
76
77 throw IllegalArgumentException("date and time must be 2-byte arrays");
78 }
79
80 /*
81 * Handle the dataIn size with signatureHi length according to card product type (3.2 rev have a
82 * 10-byte signature)
83 */
84 mDataIn = std::vector<uint8_t>(15 + (isExtendedModeAllowed ? 10 : 5));
85
86 /* mDataIn[0] will be filled in at the finalization phase */
87 const short amountShort = isDebitCommand ?
88 static_cast<short>(-amount) : static_cast<short>(amount);
89 ByteArrayUtil::copyBytes(amountShort, mDataIn, 1, 2);
90 mDataIn[3] = date[0];
91 mDataIn[4] = date[1];
92 mDataIn[5] = time[0];
93 mDataIn[6] = time[1];
94 mDataIn[7] = calypsoCard->getSvKvc();
95 /* mDataIn[8]..dataIn[8+7+sigLen] will be filled in at the finalization phase */
96}
97
99 const std::vector<uint8_t>& debitOrUndebitComplementaryData)
100{
101 if ((mIsExtendedModeAllowed && debitOrUndebitComplementaryData.size() != 20) ||
102 (!mIsExtendedModeAllowed && debitOrUndebitComplementaryData.size() != 15)) {
103
104 throw IllegalArgumentException("Bad SV prepare load data length.");
105 }
106
107 uint8_t le;
108
109 if (mIsSessionOpen) {
110 le = 0;
111 } else {
112 if(mIsExtendedModeAllowed) {
113 le = 6;
114 } else {
115 le = 3;
116 }
117 }
118
120
121 const uint8_t p1 = debitOrUndebitComplementaryData[4];
122 const uint8_t p2 = debitOrUndebitComplementaryData[5];
123
124 mDataIn[0] = debitOrUndebitComplementaryData[6];
125 System::arraycopy(debitOrUndebitComplementaryData, 0, mDataIn, 8, 4);
126 System::arraycopy(debitOrUndebitComplementaryData, 7, mDataIn, 12, 3);
127 System::arraycopy(debitOrUndebitComplementaryData,
128 10,
129 mDataIn,
130 15,
131 debitOrUndebitComplementaryData.size() - 10);
132
133 const uint8_t cardClass = getCalypsoCard()->getCardClass() == CalypsoCardClass::LEGACY ?
136
137 std::shared_ptr<ApduRequestAdapter> apduRequest;
138 if (le == 0) {
139 // APDU Case 3
140 apduRequest = std::make_shared<ApduRequestAdapter>(
141 ApduUtil::build(cardClass,
142 getCommandRef().getInstructionByte(),
143 p1,
144 p2,
145 mDataIn));
146 } else {
147 // APDU Case 4
148 apduRequest = std::make_shared<ApduRequestAdapter>(
149 ApduUtil::build(cardClass,
150 getCommandRef().getInstructionByte(),
151 p1,
152 p2,
153 mDataIn,
154 le));
155 }
156 apduRequest->addSuccessfulStatusWord(SW_POSTPONED_DATA);
157 setApduRequest(apduRequest);
158}
159
160const std::vector<uint8_t> CmdCardSvDebitOrUndebit::getSvDebitOrUndebitData() const
161{
162 std::vector<uint8_t> svDebitOrUndebitData(12);
163
164 svDebitOrUndebitData[0] = getCommandRef().getInstructionByte();
165
166 /*
167 * svDebitOrUndebitData[1,2] / P1P2 not set because ignored
168 * Lc is 5 bytes longer in product type 3.2
169 */
170 svDebitOrUndebitData[3] = mIsExtendedModeAllowed ? 0x19 : 0x14;
171
172 /* Appends the fixed part of dataIn */
173 System::arraycopy(mDataIn, 0, svDebitOrUndebitData, 4, 8);
174
175 return svDebitOrUndebitData;
176}
177
179{
180 return true;
181}
182
183void CmdCardSvDebitOrUndebit::parseApduResponse(const std::shared_ptr<ApduResponseApi> apduResponse)
184{
186
187 const std::vector<uint8_t> dataOut = apduResponse->getDataOut();
188
189 if (dataOut.size() != 0 && dataOut.size() != 3 && dataOut.size() != 6) {
190
191 throw IllegalStateException("Bad length in response to SV Debit/Undebit command.");
192 }
193
194 getCalypsoCard()->setSvOperationSignature(apduResponse->getDataOut());
195}
196
197const std::map<const int, const std::shared_ptr<StatusProperties>>
198 CmdCardSvDebitOrUndebit::initStatusTable()
199{
200 std::map<const int, const std::shared_ptr<StatusProperties>> m =
202
203 m.insert({SW_POSTPONED_DATA,
204 std::make_shared<StatusProperties>("Successful execution, response data postponed " \
205 "until session closing.",
206 typeid(nullptr))});
207 m.insert({0x6400,
208 std::make_shared<StatusProperties>("Too many modifications in session.",
209 typeid(CardSessionBufferOverflowException))});
210 m.insert({0x6700,
211 std::make_shared<StatusProperties>("Lc value not supported.",
212 typeid(CardIllegalParameterException))});
213 m.insert({0x6900,
214 std::make_shared<StatusProperties>("Transaction counter is 0 or SV TNum is FFFEh or" \
215 " FFFFh.",
216 typeid(CalypsoSamCounterOverflowException))});
217 m.insert({0x6985,
218 std::make_shared<StatusProperties>("Preconditions not satisfied.",
219 typeid(CalypsoSamAccessForbiddenException))});
220 m.insert({0x6988,
221 std::make_shared<StatusProperties>("Incorrect signatureHi.",
222 typeid(CardSecurityDataException))});
223
224 return m;
225}
226
227const std::map<const int, const std::shared_ptr<StatusProperties>>&
229{
230 return STATUS_TABLE;
231}
232
233}
234}
235}
static const std::map< const int, const std::shared_ptr< StatusProperties > > STATUS_TABLE
virtual void setApduRequest(const std::shared_ptr< ApduRequestAdapter > apduRequest) final
virtual void setExpectedResponseLength(const int expectedResponseLength) final
void parseApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
const CalypsoCardCommand & getCommandRef() const override
std::shared_ptr< CalypsoCardAdapter > getCalypsoCard() const
static const CalypsoCardClass LEGACY
static const CalypsoCardClass ISO
static const CalypsoCardClass LEGACY_STORED_VALUE
const std::vector< uint8_t > getSvDebitOrUndebitData() const
void finalizeCommand(const std::vector< uint8_t > &debitOrUndebitComplementaryData)
const std::map< const int, const std::shared_ptr< StatusProperties > > & getStatusTable() const override
void parseApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
CmdCardSvDebitOrUndebit(const bool isDebitCommand, const std::shared_ptr< CalypsoCardAdapter > calypsoCard, const int amount, const std::vector< uint8_t > &date, const std::vector< uint8_t > &time, const bool isSessionOpen, const bool isExtendedModeAllowed)