Keyple Card Calypso C++ Library 2.2.2
Reference Terminal Reader API for C++
CmdCardSvDebitOrUndebit.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2022 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 "IllegalArgumentException.h"
28#include "IllegalStateException.h"
29#include "System.h"
30
31namespace keyple {
32namespace card {
33namespace calypso {
34
35using namespace keyple::core::util;
36using namespace keyple::core::util::cpp;
37using namespace keyple::core::util::cpp::exception;
38
39const int CmdCardSvDebitOrUndebit::SV_POSTPONED_DATA_IN_SESSION = 0x6200;
40const std::map<const int, const std::shared_ptr<StatusProperties>>
41 CmdCardSvDebitOrUndebit::STATUS_TABLE = initStatusTable();
42
44 const CalypsoCardClass calypsoCardClass,
45 const int amount,
46 const uint8_t kvc,
47 const std::vector<uint8_t>& date,
48 const std::vector<uint8_t>& time,
49 const bool isExtendedModeAllowed)
50: AbstractCardCommand(isDebitCommand ? CalypsoCardCommand::SV_DEBIT :
51 CalypsoCardCommand::SV_UNDEBIT,
52 0),
53 /* Keeps a copy of these fields until the command is finalized */
54 mCalypsoCardClass(calypsoCardClass),
55 mIsExtendedModeAllowed(isExtendedModeAllowed)
56{
57 /*
58 * @see Calypso Layer ID 8.02 (200108)
59 * CL-SV-DEBITVAL.1
60 */
61 if (amount < 0 || amount > 32767) {
62 throw IllegalArgumentException("Amount is outside allowed boundaries (0 <= amount <= " \
63 "32767)");
64 }
65
66 if (date.empty() || time.empty()) {
67 throw IllegalArgumentException("date and time cannot be null");
68 }
69
70 if (date.size() != 2 || time.size() != 2) {
71 throw IllegalArgumentException("date and time must be 2-byte arrays");
72 }
73
74 /*
75 * Handle the dataIn size with signatureHi length according to card product type (3.2 rev have a
76 * 10-byte signature)
77 */
78 mDataIn = std::vector<uint8_t>(15 + (isExtendedModeAllowed ? 10 : 5));
79
80 /* mDataIn[0] will be filled in at the finalization phase */
81 const short amountShort =
82 isDebitCommand ? static_cast<short>(-amount) : static_cast<short>(amount);
83 mDataIn[1] = ((amountShort >> 8) & 0xFF);
84 mDataIn[2] = (amountShort & 0xFF);
85 mDataIn[3] = date[0];
86 mDataIn[4] = date[1];
87 mDataIn[5] = time[0];
88 mDataIn[6] = time[1];
89 mDataIn[7] = kvc;
90 /* mDataIn[8]..dataIn[8+7+sigLen] will be filled in at the finalization phase */
91}
92
94 const std::vector<uint8_t>& debitOrUndebitComplementaryData)
95{
96 if ((mIsExtendedModeAllowed && debitOrUndebitComplementaryData.size() != 20) ||
97 (!mIsExtendedModeAllowed && debitOrUndebitComplementaryData.size() != 15)) {
98 throw IllegalArgumentException("Bad SV prepare load data length.");
99 }
100
101 const uint8_t p1 = debitOrUndebitComplementaryData[4];
102 const uint8_t p2 = debitOrUndebitComplementaryData[5];
103
104 mDataIn[0] = debitOrUndebitComplementaryData[6];
105 System::arraycopy(debitOrUndebitComplementaryData, 0, mDataIn, 8, 4);
106 System::arraycopy(debitOrUndebitComplementaryData, 7, mDataIn, 12, 3);
107 System::arraycopy(debitOrUndebitComplementaryData,
108 10,
109 mDataIn,
110 15,
111 debitOrUndebitComplementaryData.size() - 10);
112
113 const uint8_t cardClass = mCalypsoCardClass == CalypsoCardClass::LEGACY ?
116
117 auto apduRequest = std::make_shared<ApduRequestAdapter>(
118 ApduUtil::build(cardClass,
119 getCommandRef().getInstructionByte(),
120 p1,
121 p2,
122 mDataIn));
123 apduRequest->addSuccessfulStatusWord(SV_POSTPONED_DATA_IN_SESSION);
124 setApduRequest(apduRequest);
125}
126
127const std::vector<uint8_t> CmdCardSvDebitOrUndebit::getSvDebitOrUndebitData() const
128{
129 std::vector<uint8_t> svDebitOrUndebitData(12);
130
131 svDebitOrUndebitData[0] = getCommandRef().getInstructionByte();
132
133 /*
134 * svDebitOrUndebitData[1,2] / P1P2 not set because ignored
135 * Lc is 5 bytes longer in product type 3.2
136 */
137 svDebitOrUndebitData[3] = mIsExtendedModeAllowed ? 0x19 : 0x14;
138
139 /* Appends the fixed part of dataIn */
140 System::arraycopy(mDataIn, 0, svDebitOrUndebitData, 4, 8);
141
142 return svDebitOrUndebitData;
143}
144
146{
147 return true;
148}
149
151 const std::shared_ptr<ApduResponseApi> apduResponse)
152{
154
155 const std::vector<uint8_t> dataOut = apduResponse->getDataOut();
156 if (dataOut.size() != 0 && dataOut.size() != 3 && dataOut.size() != 6) {
157 throw IllegalStateException("Bad length in response to SV Debit/Undebit command.");
158 }
159
160 return *this;
161}
162
163const std::vector<uint8_t> CmdCardSvDebitOrUndebit::getSignatureLo() const
164{
165 return getApduResponse()->getDataOut();
166}
167
168const std::map<const int, const std::shared_ptr<StatusProperties>>
169 CmdCardSvDebitOrUndebit::initStatusTable()
170{
171 std::map<const int, const std::shared_ptr<StatusProperties>> m =
173
174 m.insert({SV_POSTPONED_DATA_IN_SESSION,
175 std::make_shared<StatusProperties>("Successful execution, response data postponed " \
176 "until session closing.",
177 typeid(nullptr))});
178 m.insert({0x6400,
179 std::make_shared<StatusProperties>("Too many modifications in session.",
180 typeid(CardSessionBufferOverflowException))});
181 m.insert({0x6700,
182 std::make_shared<StatusProperties>("Lc value not supported.",
183 typeid(CardIllegalParameterException))});
184 m.insert({0x6900,
185 std::make_shared<StatusProperties>("Transaction counter is 0 or SV TNum is FFFEh or" \
186 " FFFFh.",
187 typeid(CalypsoSamCounterOverflowException))});
188 m.insert({0x6985,
189 std::make_shared<StatusProperties>("Preconditions not satisfied.",
190 typeid(CalypsoSamAccessForbiddenException))});
191 m.insert({0x6988,
192 std::make_shared<StatusProperties>("Incorrect signatureHi.",
193 typeid(CardSecurityDataException))});
194
195 return m;
196}
197
198const std::map<const int, const std::shared_ptr<StatusProperties>>&
200{
201 return STATUS_TABLE;
202}
203
204}
205}
206}
static const std::map< const int, const std::shared_ptr< StatusProperties > > STATUS_TABLE
virtual const std::shared_ptr< ApduResponseApi > getApduResponse() const final
virtual void setApduRequest(const std::shared_ptr< ApduRequestAdapter > apduRequest) final
const CalypsoCardCommand & getCommandRef() const override
AbstractCardCommand & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
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::vector< uint8_t > getSignatureLo() const
const std::map< const int, const std::shared_ptr< StatusProperties > > & getStatusTable() const override
CmdCardSvDebitOrUndebit & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
CmdCardSvDebitOrUndebit(const bool isDebitCommand, const CalypsoCardClass calypsoCardClass, const int amount, const uint8_t kvc, const std::vector< uint8_t > &date, const std::vector< uint8_t > &time, const bool isExtendedModeAllowed)