Exemple #1
0
 public TxCompletedEventArgs(TxResult txResult, InterFaceType interFaceType, Optional <TLV> emvData, Optional <QRDEList> qr_Data)
 {
     TxResult      = txResult;
     InterFaceType = interFaceType;
     EMV_Data      = emvData;
     QR_Data       = qr_Data;
 }
Exemple #2
0
 private void cmdCancelTx_Clicked(object sender, EventArgs e)
 {
     Stop();
     txResult = TxResult.Cancelled;
     SetTxFinalResultLabel("");
     SetStatusLabel(new UIMessageEventArgs(MessageIdentifiersEnum.ClearDisplay, StatusEnum.EndProcessing), InterFaceType.Cancelled);
     TxCompleted?.Invoke(this, new TxCompletedEventArgs(txResult, InterFaceType.Cancelled, Optional <TLV> .CreateEmpty(), Optional <QRDEList> .CreateEmpty()));
 }
Exemple #3
0
        private void Start()
        {
            txResult = TxResult.Error;
            cancellationTokenForStatusMessage = new CancellationTokenSource();

            //txtPin.Text = "";
            txtPin.Text = "4315";

            StartStatusMessageProcessor();
            StartContactPaymentApp(contactDeviceId);
            StartContactlessPaymentApp(contactlessDeviceId);

            UpdateView(ViewState.Step2TapCard);//call after TransactionRequest is created
        }
Exemple #4
0
        private static NodeEffect[] ParseEffects(Tx tx, AffectedNode[] affectedNodes, string account, TxResult result)
        {
            if (affectedNodes == null || affectedNodes.Length == 0)
            {
                return(null);
            }

            var effects = new List <NodeEffect>();

            foreach (var an in affectedNodes)
            {
                var        diffType   = an.DiffType;
                var        node       = an.CreatedNode ?? an.DeletedNode ?? an.ModifiedNode;
                var        fieldsSet  = new FieldsSet(node.FinalFields, node.PreviousFields, node.NewFields);
                NodeEffect nodeEffect = null;

                //TODO now only get offer related effects, need to process other entry type

                if (node.LedgerEntryType == "Offer")
                {
                    // for new and cancelled offers
                    var         sell        = fieldsSet.Flags == (long)LedgerOfferFlags.Sell;
                    OfferEffect offerEffect = null;

                    // current account offer
                    if (fieldsSet.Account == account)
                    {
                        // 1. offer_partially_funded
                        var seq = fieldsSet.Sequence;
                        if (diffType == DiffType.ModifiedNode || (diffType == DiffType.DeletedNode && node.PreviousFields != null && node.PreviousFields.TakerGets != null && !IsAmountZero(node.FinalFields.TakerGets)))
                        {
                            var partiallyFoundedEffect = new OfferPartiallyFundedEffect();
                            offerEffect = partiallyFoundedEffect;
                            partiallyFoundedEffect.Seq = seq;

                            partiallyFoundedEffect.CounterParty = new CounterParty {
                                Account = tx.Account, Seq = tx.Sequence, Hash = tx.Hash
                            };
                            if (diffType == DiffType.DeletedNode)
                            {
                                partiallyFoundedEffect.Cancelled = true;
                            }
                            else
                            {
                                // TODO no need partially funded must remains offers
                                partiallyFoundedEffect.Remaining = !IsAmountZero(fieldsSet.TakerGets);
                            }

                            var gets = fieldsSet.TakerGets;
                            var pays = fieldsSet.TakerPays;
                            partiallyFoundedEffect.Gets = gets;
                            partiallyFoundedEffect.Pays = pays;
                            partiallyFoundedEffect.Got  = AmountSubtract(node.PreviousFields.TakerPays, pays);
                            partiallyFoundedEffect.Paid = AmountSubtract(node.PreviousFields.TakerGets, gets);
                            partiallyFoundedEffect.Type = sell ? OfferEffectType.Sold : OfferEffectType.Bought;
                        }
                        else
                        {
                            // offer_funded, offer_created or offer_cancelled offer effect
                            var effect = diffType == DiffType.CreatedNode ? EffectType.OfferCreated : (node.PreviousFields != null && node.PreviousFields.TakerPays != null ? EffectType.OfferFunded : EffectType.OfferCancelled);
                            switch (effect)
                            {
                            // 2. offer_funded
                            case EffectType.OfferFunded:
                                var fundedfEffect = new OfferFundedEffect();
                                fundedfEffect.Seq = seq;
                                offerEffect       = fundedfEffect;

                                fundedfEffect.CounterParty = new CounterParty {
                                    Account = tx.Account, Seq = tx.Sequence, Hash = tx.Hash
                                };
                                fundedfEffect.Got  = AmountSubtract(node.PreviousFields.TakerPays, fieldsSet.TakerPays);
                                fundedfEffect.Paid = AmountSubtract(node.PreviousFields.TakerGets, fieldsSet.TakerGets);
                                fundedfEffect.Type = sell ? OfferEffectType.Sold : OfferEffectType.Bought;
                                break;

                            // 3. offer_created
                            case EffectType.OfferCreated:
                                var createdEffect = new OfferCreatedEffect();
                                createdEffect.Seq = seq;
                                offerEffect       = createdEffect;

                                createdEffect.Gets = fieldsSet.TakerGets;
                                createdEffect.Pays = fieldsSet.TakerPays;
                                createdEffect.Type = sell ? OfferEffectType.Sell : OfferEffectType.Buy;
                                break;

                            // 4. offer_cancelled
                            case EffectType.OfferCancelled:
                                var cancelledEffect = new OfferCancelledEffect();
                                cancelledEffect.Seq = seq;
                                offerEffect         = cancelledEffect;

                                cancelledEffect.Gets = fieldsSet.TakerGets;
                                cancelledEffect.Pays = fieldsSet.TakerPays;
                                cancelledEffect.Type = sell ? OfferEffectType.Sell : OfferEffectType.Buy;

                                // collect data for cancel transaction type
                                if (result.Type == TxResultType.OfferCancel)
                                {
                                    var cancelResult = result as OfferCancelTxResult;
                                    cancelResult.Gets = cancelledEffect.Gets;
                                    cancelResult.Pays = cancelledEffect.Pays;
                                }

                                break;
                            }
                        }
                    }
                    // 5. offer_bought
                    else if (tx.Account == account && node.PreviousFields != null)
                    {
                        var boughtEffect = new OfferBoughtEffect();
                        offerEffect = boughtEffect;

                        boughtEffect.CounterParty = new CounterParty {
                            Account = fieldsSet.Account, Seq = fieldsSet.Sequence, Hash = node.PreviousTxnID ?? fieldsSet.PreviousTxnID
                        };
                        boughtEffect.Paid = AmountSubtract(node.PreviousFields.TakerPays, fieldsSet.TakerPays);
                        boughtEffect.Got  = AmountSubtract(node.PreviousFields.TakerGets, fieldsSet.TakerGets);
                        boughtEffect.Type = sell ? OfferEffectType.Bought : OfferEffectType.Sold;
                    }

                    // add price
                    if (offerEffect != null && offerEffect.GotOrPays != null && offerEffect.PaidOrGets != null)
                    {
                        var created          = offerEffect.Effect == EffectType.OfferCreated && offerEffect.Type == OfferEffectType.Buy;
                        var funded           = offerEffect.Effect == EffectType.OfferFunded && offerEffect.Type == OfferEffectType.Bought;
                        var cancelled        = offerEffect.Effect == EffectType.OfferCancelled && offerEffect.Type == OfferEffectType.Buy;
                        var bought           = offerEffect.Effect == EffectType.OfferBought && offerEffect.Type == OfferEffectType.Bought;
                        var partially_funded = offerEffect.Effect == EffectType.OfferPartiallyFunded && offerEffect.Type == OfferEffectType.Bought;
                        var offerFunded      = created || funded || cancelled || bought || partially_funded;
                        offerEffect.Price = GetPrice(offerEffect.GotOrPays, offerEffect.PaidOrGets, offerFunded);
                    }

                    nodeEffect = offerEffect;
                }
                else if (node.LedgerEntryType == "AccountRoot")
                {
                    if (result.Type == TxResultType.OfferEffect)
                    {
                        if (fieldsSet.RegularKey == account)
                        {
                            var regularKeyEffect = new SetRegularKeyEffect();
                            nodeEffect = regularKeyEffect;

                            regularKeyEffect.Type       = "null";
                            regularKeyEffect.Account    = fieldsSet.Account;
                            regularKeyEffect.RegularKey = account;
                        }
                    }
                }

                if (nodeEffect != null)
                {
                    effects.Add(nodeEffect);

                    if (diffType == DiffType.DeletedNode && nodeEffect.Effect != EffectType.OfferBought)
                    {
                        nodeEffect.Deleted = true;
                    }
                }
            }

            return(effects.ToArray());
        }
Exemple #5
0
        private void ProcessCompletion(TerminalProcessingOutcomeEventArgs e, InterFaceType interFaceType)
        {
            TLV      data = null;
            TLV      discretionaryData = null;
            QRDEList qrData            = null;

            try
            {
                long?amount = Convert.ToInt64(totalAmount.Total);

                TerminalProcessingOutcome tpo = e.TerminalProcessingOutcome;
                if (tpo == null)//error occurred, error displayed via Ta_ExceptionOccured
                {
                    return;
                }

                if (tpo is EMVTerminalProcessingOutcome)
                {
                    data = ((EMVTerminalProcessingOutcome)tpo).DataRecord;
                    discretionaryData = ((EMVTerminalProcessingOutcome)tpo).DiscretionaryData;
                    qrData            = ((EMVTerminalProcessingOutcome)tpo).QRData;

                    if (data != null) //error
                    {
                        SetStatusLabel(new UIMessageEventArgs(MessageIdentifiersEnum.RemoveCard, StatusEnum.EndProcessing), interFaceType);

                        //may be a contactless magstripe transaction
                        if (data.Children.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag) == null)
                        {
                            txResult = TxResult.ContactlessMagOnline;
                        }
                        else
                        {
                            if (((data.Children.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag).Value[0] & 0xC0) >> 6) == (byte)ACTypeEnum.ARQC)
                            {
                                if (interFaceType == InterFaceType.Contact)
                                {
                                    throw new EMVProtocolException("Invalid state for contact, gen ac 2 returned arqc?");
                                }

                                CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvmr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(data.Children.Get(EMVTagsEnum.CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN.Tag));
                                if (cvmr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline)
                                {
                                    ContactlessApp_PinRequest(data.Children);
                                }

                                txResult = TxResult.ContactlessOnline;
                            }
                            if (((data.Children.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag).Value[0] & 0xC0) >> 6) == (byte)ACTypeEnum.TC)
                            {
                                txResult = TxResult.Approved;
                            }
                            if (((data.Children.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag).Value[0] & 0xC0) >> 6) == (byte)ACTypeEnum.AAC)
                            {
                                txResult = TxResult.Declined;
                            }
                        }
                    }
                    else if (qrData != null)
                    {
                        if (interFaceType == InterFaceType.QRCodeScanned)
                        {
                            txResult = TxResult.QRCodeScanned;
                        }
                        else if (interFaceType == InterFaceType.QRCodeToPoll)
                        {
                            txResult = TxResult.QRCodeToPoll;
                        }
                    }
                    else
                    {
                        txResult = TxResult.Declined;
                    }

                    SetTxFinalResultLabel(txResult.ToString());
                }
                else
                {
                    SetStatusLabel(new UIMessageEventArgs(tpo.UserInterfaceRequest.MessageIdentifier, tpo.UserInterfaceRequest.Status), interFaceType);
                }
            }
            catch (Exception ex)
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    UIMessageEventArgs ui = new UIMessageEventArgs(MessageIdentifiersEnum.TryAgain, StatusEnum.ProcessingError)
                    {
                        AdditionalMessage = ex.Message
                    };
                    SetStatusLabel(ui, interFaceType);
                });
            }
            finally
            {
                StopContactPaymentApp();
                StopContactlessPaymentApp();
                StopQRCodePollPaymentApp();

                #region Merge EMV Lists
                if (discretionaryData != null)
                {
                    if (data != null)
                    {
                        data.Children.AddListToList(discretionaryData.Children);
                    }
                }
                #endregion

                TxCompleted?.Invoke(this, new TxCompletedEventArgs(txResult, interFaceType, Optional <TLV> .Create(data), Optional <QRDEList> .Create(qrData)));
            }
        }