Beispiel #1
0
        /// <summary>
        /// 發送通知給特定user
        /// todo : 僅用於測試,待移除或權限控管
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task <IRpcMethodResult> sendMessage(string userId, string message)
        {
            var user = db.getUserByUserId(userId);

            await notifications.sendMessage(userId, user.ntfInfo.pns, message);

            return(Ok());
        }
Beispiel #2
0
        /// <summary>
        /// 發送通知給特定user
        /// todo : 僅用於測試,待移除或權限控管
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task <IRpcMethodResult> sendMessage(string userId, string message)
        {
            var uid = UserHelper.IdGen.Parse(userId);

            var userHelper = new UserHelper();

            var user = await userHelper.GetById(uid);

            await notifications.sendMessage(user.userId, user.ntfInfo.pns, message);

            return(Ok());
        }
Beispiel #3
0
        /// <summary>
        /// 轉帳(付款)
        /// </summary>
        /// <param name="fromId"></param>
        /// <param name="toId"></param>
        /// <param name="currency"></param>
        /// <param name="amount"></param>
        /// <returns>receiptId</returns>
        public async Task <bool> doTransfer(string fromId, string toId, string receiptId, string currency, decimal amount, string message)
        {
            var ok = false;

            //get user
            var fromUser = getUserByUserId(fromId);
            var toUser   = getUserByUserId(toId);

            //get user's balance
            var from_balance = getBalance(fromId).balances[currency];
            var to_balance   = getBalance(toId).balances[currency];

            //simulate transcation
            if (!fromId.Equals(toId))
            {
                if (amount > 0 && (from_balance >= amount))
                {
                    from_balance = from_balance - (fromUser.phoneno == "BANK" ? 0 : amount);
                    to_balance   = to_balance + amount;

                    updateBalance(fromId, new Dictionary <string, decimal> {
                        { currency, from_balance }
                    });
                    updateBalance(toId, new Dictionary <string, decimal> {
                        { currency, to_balance }
                    });
                    ok = true;
                }
            }

            //generate sender receipt
            var param = new TxParams
            {
                sender   = fromUser.userId,
                receiver = toUser.userId,
                currency = currency,
                amount   = amount
            };
            var sender_rec = new TxReceipt
            {
                receiptId  = receiptId,
                executorId = fromUser.userId,
                ownerId    = fromUser.userId,
                currency   = currency,
                message    = message,
                isParent   = true,

                txType     = TxType.TRANSFER,
                statusCode = ok ? 0 : -1,
                statusMsg  = "",
                txParams   = param,
                txResult   = !ok ? null : new TxActResult
                {
                    outflow = true,
                    amount  = amount,
                    balance = from_balance
                }
            };

            upsertReceipt(sender_rec);

            //simulate receipt notification
            Task.Run(async() =>
            {
                Task.Delay(10).Wait();
                //notify sender
                // if (fromUser.ntfInfo != null)
                //     notifications.sendMessage(fromId, fromUser.ntfInfo.pns, $"transfer out({(ok ? "okay" : "failure")})", D.NTFTYPE.TXRECEIPT, new { list = new List<dynamic>() { sender_rec.ToApiResult() } });

                //notify receiver
                if (ok && toUser.ntfInfo != null)
                {
                    //generate receiver receipt
                    var receiver_rec = sender_rec.Derivative(sender_rec.currency, toUser.userId, new TxActResult
                    {
                        outflow = false,
                        amount  = amount,
                        balance = to_balance
                    });
                    upsertReceipt(receiver_rec);

                    await notifications.sendMessage(toId, toUser.ntfInfo.pns, "transfer in", D.NTFTYPE.TXRECEIPT, new { list = new List <dynamic>()
                                                                                                                        {
                                                                                                                            receiver_rec.ToApiResult()
                                                                                                                        } });
                }
            }).Start();

            return(ok);
        }
Beispiel #4
0
        /// <summary>
        /// 登入API service
        /// </summary>
        /// <param name="phoneno"></param>
        /// <param name="passcode"></param>
        /// <returns></returns>
        public async Task <IRpcMethodResult> login(string phoneno, string passcode, PNS pns, string pnsToken)
        {
            var smsHelper  = new SmsPasscodeHelper();
            var userHelper = new UserHelper();

            try
            {
                // todo : remove this
                Console.WriteLine("萬用passcode未移除!");
                if (passcode == "88888888")
                {
                }
                else
                {
                    // 驗證sms passcode
                    dynamic res = await smsHelper.IsSmsPasscodeMatched(phoneno, passcode);

                    // 驗證失敗
                    if (!res.passed)
                    {
                        return(Bad(res.error));
                    }
                }

                // 取得user
                var user = await userHelper.GetByPhoneno(phoneno);

                var uid = (user != null) ? UserHelper.IdGen.Parse(user.userId) : userHelper.GenUid();

                var tokenRnd = F.NewGuid();
                var jwt      = IssueToken(uid, tokenRnd);
                var jwtHash  = tokenRnd.ToHash(); //todo : each user should have their own signature to verify

                //sign up
                if (user == null)
                {
                    // create new user
                    user = await userHelper.Create(uid, jwtHash, phoneno, phoneno);

                    // reg pns token
                    var nc = (RpcNotification)this.accessor.HttpContext.RequestServices.GetService(typeof(RpcNotification));
                    await nc.regPnsToken(pns, pnsToken, user);

                    // db.addFriends(user.userId, new List<string> { });
                    // db.updateBalance(user.userId, new Dictionary<string, decimal>());
                }
                //sign in
                else
                {
                    // 通知前裝置必須登出
                    var ntfInfo = user.ntfInfo;
                    if (ntfInfo != null && (ntfInfo.pns != pns || ntfInfo.pnsRegId != pnsToken))
                    {
                        await notifications.sendMessage(user.userId, ntfInfo.pns, "someone logged into your account\\nyou've got to logout!(t1)", D.NTFTYPE.LOGOUT);

                        // 避免rpc時間差可能造成regPnsToken在sendMessage之前
                        Task.Delay(3000).Wait();
                    }

                    // 更新裝置pns token
                    if (ntfInfo == null || ntfInfo.pns != pns || ntfInfo.pnsRegId != pnsToken)
                    {
                        var nc = (RpcNotification)this.accessor.HttpContext.RequestServices.GetService(typeof(RpcNotification));
                        await nc.regPnsToken(pns, pnsToken, user);
                    }

                    // update token hash
                    user.jwtHash = jwtHash;
                    await userHelper.Update(user);
                }

                return(Ok(new { token = jwt }));
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return(ERROR_ACT_FAILED);
        }
Beispiel #5
0
        /// <summary>
        /// 登入API service
        /// </summary>
        /// <param name="phoneno"></param>
        /// <param name="passcode"></param>
        /// <returns></returns>
        public async Task <IRpcMethodResult> login(string phoneno, string passcode, PNS pns, string pnsToken)
        {
            try
            {
                // 驗證sms passcode
                dynamic res = db.isSmsPasscodeMatched(phoneno, passcode);

                // todo : remove this
                Console.WriteLine("萬用passcode未移除!");
                if (passcode == "88888888")
                {
                }
                else

                // 驗證失敗
                if (!res.passed)
                {
                    return(Bad(res.error));
                }

                // 建立或取得user
                var user = db.getUserByPhone(phoneno);
                if (user != null)
                {
                    // 通知前裝置必須登出
                    var ntfInfo = user.ntfInfo;
                    if (ntfInfo != null && (ntfInfo.pns != pns || ntfInfo.pnsRegId != pnsToken))
                    {
                        await Task.Run(async() =>
                        {
                            await notifications.sendMessage(user.userId, ntfInfo.pns, "someone logged into your account\\nyou've got to logout!(t1)", D.NTFTYPE.LOGOUT);
                            // 避免rpc時間差可能造成regPnsToken在sendMessage之前
                            Task.Delay(3000).Wait();
                        });
                    }

                    // 更新裝置pns token
                    if (ntfInfo == null || ntfInfo.pns != pns || ntfInfo.pnsRegId != pnsToken)
                    {
                        var nc = (RpcNotification)this.accessor.HttpContext.RequestServices.GetService(typeof(RpcNotification));
                        await nc.regPnsToken(pns, pnsToken, user);
                    }
                }
                else
                {
                    //todo : 暫時的假資料供測試
                    user = new User()
                    {
                        userId  = "tempid-" + phoneno, //todo : 暫時以phoneno綁定id 便於識別 (日後移除)
                        phoneno = phoneno,
                        name    = phoneno,
                        // avatar = "https://ionicframework.com/dist/preview-app/www/assets/img/avatar-ts-woody.png",
                        avatar     = "", //empty for default
                        currencies = new List <CurrencySettings> {
                            new CurrencySettings {
                                name      = D.CNY,
                                order     = 0,
                                isDefault = true,
                                isVisible = false
                            },
                            new CurrencySettings {
                                name      = D.USD,
                                order     = 1,
                                isDefault = false,
                                isVisible = false
                            },
                            new CurrencySettings {
                                name      = D.BTC,
                                order     = 2,
                                isDefault = false,
                                isVisible = false
                            },
                            new CurrencySettings {
                                name      = D.ETH,
                                order     = 3,
                                isDefault = false,
                                isVisible = false
                            }
                        }
                    };
                    if (db.upsertUser(user))
                    {
                        user = db.getUserByPhone(phoneno);
                    }

                    var nc = (RpcNotification)this.accessor.HttpContext.RequestServices.GetService(typeof(RpcNotification));
                    await nc.regPnsToken(pns, pnsToken, user);

                    db.addFriends(user.userId, new List <string> {
                    });
                    db.updateBalance(user.userId, new Dictionary <string, decimal>());
                }

                // 發行token (JWT)
                var tokenRnd = F.NewGuid();
                var claims   = new Claim[] {
                    new Claim(ClaimTypes.MobilePhone, phoneno),
                    new Claim(ClaimTypes.Name, user.name),
                    new Claim(ClaimTypes.Role, "User"),
                    new Claim(D.CLAIM.USERID, user.userId),
                    new Claim(D.CLAIM.TOKENRND, tokenRnd)
                };
                var key   = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(R.JWT_SECRET));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var token = new JwtSecurityToken(
                    R.JWT_ISSUER,
                    R.JWT_AUDIENCE,
                    claims,
                    null,         //DateTime.UtcNow, //todo : 日後再決定是否每次token帶入時間加密
                    null,
                    creds);
                var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);

                // update token random
                user.tokenRnd = tokenRnd;
                db.upsertUser(user);

                return(Ok(new { token = tokenStr }));
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return(ERROR_ACT_FAILED);
        }