Tìm kiếm


    Tích hợp thanh toán MoMo với ASP.NET Core


    Giới thiệu

    Ở một số bài viết trước mình đã hướng dẫn cách tích hợp VnPay, PayPal vào website với ASP.NET Core.

    Và để tiếp tục seri này thì mình sẽ hướng dẫn các bạn tích hợp MoMo vào ASP.NET Core để các bạn có nhiều lựa chọn hơn.

    Tích Hợp Thanh Toán Online VnPay Vào .Net Core

     Tích Hợp Thanh Toán Online PayPal Với .Net Core

    Chuẩn bị phần mêm cần thiết

    Các bạn cần chuẩn bị một IDE hỗ trợ code C# sịn sò cho mình. Các bạn có thể xem Top các IDE dành cho C# TẠI ĐÂY

    Ở đây mình sử dụng Rider :D

    Tải App MoMo Test

    Do mình sử dụng Tài Khoản Test của MoMo nên chúng ta cần App MoMo Test để có thể thực hiện thanh toán.

    Các bạn truy cập vào trang https://developers.momo.vn/v3/vi/download/ để tải App về nhé.

    Đối với bạn nào sử dụng IOS sau khi cài sẽ có thông báo Nhà phát triển Doanh nghiệp không được tin cậy khi mở App thì các bạn làm như sau để có thể vào App:

    ád

    Tạo Ví TEST Mới

    Bước 1. Nhập một số điện thoại đúng ngẫu nhiên (10 số)

    Bạn nên sử dụng các đầu số đúng với các Nhà mạng hiện hành. Tham khảo

    Bước 2. Nhập OTP

    Ứng dụng sẽ yêu cầu bạn nhập mã OTP. Mã này sẽ được đặt MẶC ĐỊNH là:

    • 0000 hoặc 000000 trên App MoMo Test.

     

    Bước 3. Tạo mật khẩu 6 chữ số

    Bước 4. Điền thông tin cá nhân.

    • - Họ & tên: Họ [Khoảng trống] Tên
    • - Email
    • - Giới tính
    • - Quốc gia: chọn Việt Nam

     

    Liên kết ngân hàng & và thêm số dư Ví.

    Để thanh toán được và thêm số dư, bạn cần liên kết tài khoản với ít nhất một thẻ ngân hàng.

    Cách liên kết với thẻ ngân hàng nội địa:

    Bước 1. Ở góc phải phía bên dưới chọn "Ví của tôi" -> "Liên kết tài khoản" hoặc chọn "Nạp tiền" ngay tại góc trái màn hình chính.

    Bước 2. Chọn ngân hàng (nhớ chọn Agribank nhé) -> "Liên kết bằng số thẻ ATM"

    Bước 3. Nhập thông tin thẻ ATM. Thông tin này các bạn nhập gì cũng được

    • - Số thẻ: 9704 05XX XXXX XXXX (16 chữ số, X là số bất kỳ từ 0-9. 6 số đầu bắt buộc là 9704 05)
    • - Họ và tên chủ thẻ
    • - Ngày phát hành

     

    Bước 4. Nạp tiền

    Màn hình chính -> Nạp tiền -> Nhập số tiền -> Nhập mật khẩu -> Nhập OTP (nếu có). Mặc định là 0000 hoặc 000000

    Trong 24 giờ đầu sau khi tạo, bạn có thể gặp phải một số hạn chế người dùng liên quan đến việc kiểm soát số dư. Bạn có thể tắt App hoặc chờ một lúc và thử lại. Nếu đã thử các cách trên mà bạn vẫn tiếp tục gặp vấn đề, xin vui lòng liên hệ MoMo.

    Một Vài Thông Tin Quan Trọng

    Ở đây mình sử dụng thông tin Test của MoMo cung cấp sẵn. Bạn nào đăng ký Tài Khoản riêng hoặc Tài Khoản Production thì vào https://business.momo.vn/ để đăng ký nhá.

    HTTP Request

    • - Content-Type: application/json; charset=UTF-8
    • - Method: POST
    • - URL: Production: https://payment.momo.vn  Sandbox: https://test-payment.momo.vn

     

    Ở đây mình sử dụng URL https://test-payment.momo.vn

    MoMo sử dụng chữ ký điện tử và mã hoá dữ liệu để xác thực dữ liệu đầu vào và ra trên mỗi yêu cầu HTTP Request/HTTP Response.

    Chữ ký điện tử

    signature là một chuỗi ký tự được tạo ra từ một thuật toán cho trước, sử dụng để kiểm tra tính đúng đắn của dữ liệu trên đường truyền giữa 2 hệ thống. Một số thuật toán đang sử dụng là MD5, SHA1, SHA256 và Hmac.

    MoMo sử dụng thuật toán HMAC_SHA256 để tạo signature. Dữ liệu đầu vào bao gồm Secret Keydata, data được tạo ra theo định dạng: key1=value1&key2=value2...

    key1: tên field, value1 = giá trị của key1.

    Ví dụ

    {
      "accessKey": "F8BBA842ECF85",
      "partnerCode": "MOMO",
      "requestType": "captureMoMoWallet",
      "notifyUrl": "https://progcoder.com",
      "returnUrl": "https://progcoder.com",
      "orderId": "1540456472575",
      "amount": "150000",
      "orderInfo": "Thanh toán tại ProG Coder",
      "requestId": "1540456472575",
      "extraData": "",
      "signature": "996ed81d68a1b05c99516835e404b2d0146d9b12fbcecbf80c7e51df51cac85e"
    }
    

    data được tạo =>

    partnerCode=MOMO&accessKey=F8BBA842ECF85&requestId=1540456472575&amount=150000&orderId=1540456472575&orderInfo=Thanh toán tại ProG Coder&returnUrl=https://progcoder.com¬ifyUrl=https://progcoder.com&extraData=

    Secret KeyK951B6PE1waDMi640xX08PD3vg6EkVlz

    signature lúc này sẽ được tạo như sau:

    // Ví dụ này mình sử dụng Javascript để tạo signature 
    
    var signature = HmacSHA256(data, secretkey);
    console.log(signature);
    
    996ed81d68a1b05c99516835e404b2d0146d9b12fbcecbf80c7e51df51cac85e
    

    Lưu Ý: 

    • - Access Key
    • - Secret Key

     

    2 key này các bạn cần thay đổi để có thể sử dụng cho môi trường Production nhé. Còn nếu test thì có thể sử dụng lại key trong bài viết của mình

    Setup Code

    Trong file appsetting.json các bạn thêm đoạn code như sau đồng thời sửa lại các thông tin SecretKey, AccessKey bằng thông tin của các bạn vừa đăng ký

      "MomoAPI": {
        "MomoApiUrl": "https://test-payment.momo.vn/gw_payment/transactionProcessor",
        "SecretKey": "K951B6PE1waDMi640xX08PD3vg6EkVlz",
        "AccessKey": "F8BBA842ECF85",
        "ReturnUrl": "https://localhost:5001/Home/PaymentCallBack",
        "NotifyUrl": "https://localhost:5001/Home/MomoNotify",
        "PartnerCode": "MOMO",
        "RequestType": "captureMoMoWallet"
      },

    ReturnUrl sẽ được MoMo redirect tới kèm một số thông tin sau khi thanh toán thành công hoặc thất bại

    NotifyUrl MoMo sẽ call tới URL này khi một transaction hoàn tất (Chỉ thực hiện được trên Domain thật nghĩa là nó sẽ không call được tại Localhost các bạn nhé)

    Code Chính

    Như mình đã nói ở trên MoMo cần tạo ra signature với mã hóa SHA256 cho mỗi request nên mình sẽ viết một hàm để mã hóa như sau:

    private string ComputeHmacSha256(string message, string secretKey)
    {
        var keyBytes = Encoding.UTF8.GetBytes(secretKey);
        var messageBytes = Encoding.UTF8.GetBytes(message);
    
        byte[] hashBytes;
    
        using (var hmac = new HMACSHA256(keyBytes))
        {
            hashBytes = hmac.ComputeHash(messageBytes);
        }
    
        var hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
    
        return hashString;
    }

    CreatePaymentAsync

    public async Task CreatePaymentAsync(OrderInfoModel model)
    {
        model.OrderId = DateTime.UtcNow.Ticks.ToString();
        model.OrderInfo = "Khách hàng: " + model.FullName + ". Nội dung: " + model.OrderInfo;
        var rawData =
            $"partnerCode={_options.Value.PartnerCode}&accessKey={_options.Value.AccessKey}&requestId={model.OrderId}&amount={model.Amount}&orderId={model.OrderId}&orderInfo={model.OrderInfo}&returnUrl={_options.Value.ReturnUrl}¬ifyUrl={_options.Value.NotifyUrl}&extraData=";
    
        var signature = ComputeHmacSha256(rawData, _options.Value.SecretKey);
    
        var client = new RestClient(_options.Value.MomoApiUrl);
        var request = new RestRequest() { Method = Method.Post };
        request.AddHeader("Content-Type", "application/json; charset=UTF-8");
    
        // Create an object representing the request data
        var requestData = new
        {
            accessKey = _options.Value.AccessKey,
            partnerCode = _options.Value.PartnerCode,
            requestType = _options.Value.RequestType,
            notifyUrl = _options.Value.NotifyUrl,
            returnUrl = _options.Value.ReturnUrl,
            orderId = model.OrderId,
            amount = model.Amount.ToString(),
            orderInfo = model.OrderInfo,
            requestId = model.OrderId,
            extraData = "",
            signature = signature
        };
    
        request.AddParameter("application/json", JsonConvert.SerializeObject(requestData), ParameterType.RequestBody);
    
        var response = await client.ExecuteAsync(request);
    
        return JsonConvert.DeserializeObject(response.Content);
    }

    Với hàm CreatePaymentAsync mình sẽ gửi request tới MoMo để lấy URL thanh toán của MoMo

    Kết quả thành công sẽ có dạng:

    {
      "requestId": "638206149219469347",
      "errorCode": 0,
      "orderId": "638206149219469347",
      "message": "Success",
      "localMessage": "Thành công",
      "requestType": "captureMoMoWallet",
      "payUrl": "https://test-payment.momo.vn/v2/gateway/pay?t=TU9NT3w2MzgyMDYxNDkyMTk0NjkzNDc",
      "signature": "9d8cd820faeccf2084a03cfc08623347345db7ec5942aca1651ddae016d02e4e",
      "qrCodeUrl": "momo://app?action=payWithApp&isScanQR=true&serviceType=qr&sid=TU9NT3w2MzgyMDYxNDkyMTk0NjkzNDc&v=2.3",
      "deeplink": "momo://app?action=payWithApp&isScanQR=false&serviceType=app&sid=TU9NT3w2MzgyMDYxNDkyMTk0NjkzNDc&v=2.3",
      "deeplinkWebInApp": "https://test-payment.momo.vn/gw_payment/waiting//momo//?type=webinapp&action=payment&requestId=638206149219469347&billId=638206149219469347&partnerCode=MOMO&partnerName=MoMo Payment&amount=10000&description=Khách hàng: ProG Coder. Nội dung: Thanh toán tại ProG Coder¬ifyUrl=https://localhost:5001/Home/MomoNotify&returnUrl=https://localhost:5001/Home/PaymentCallBack&code=momo&extraData=eyJzaWduYXR1cmUiOiIwOWVlNzllMDYyOTdkZDk1NWMzZTBhMjQ5YWE2NjVjNWE5ODE1OGRlNjMyY2I5ZDA1ZTFhMGZmZTg5OTE4NGQ3In0=&signature=09ee79e06297dd955c3e0a249aa665c5a98158de632cb9d05e1a0ffe899184d7"
    }

    Mình sẽ sử dụng payUrl trong response để redirect qua trang thanh toán của MoMo và thực hiện giao dịch.

    PaymentExecuteAsync

    public MomoExecuteResponseModel PaymentExecuteAsync(IQueryCollection collection)
    {
        var amount = collection.First(s => s.Key == "amount").Value;
        var orderInfo = collection.First(s => s.Key == "orderInfo").Value;
        var orderId = collection.First(s => s.Key == "orderId").Value;
        return new MomoExecuteResponseModel()
        {
            Amount = amount,
            OrderId = orderId,
            OrderInfo = orderInfo
        };
    }

    Trong hàm xử lý này sẽ lấy ra các thông tin sau khi giao dịch tại MoMo

    Controller

    Trong Controller mình sẽ gọi ra 2 Services trên như sau:

    private IMomoService _momoService;
    
    public HomeController(IMomoService momoService)
    {
        _momoService = momoService;
    }
    
    public IActionResult Index()
    {
        return View();
    }
    
    [HttpPost]
    public async Task CreatePaymentUrl(OrderInfoModel model)
    {
        var response = await _momoService.CreatePaymentAsync(model);
        return Redirect(response.PayUrl);
    }
    
    [HttpGet]
    public IActionResult PaymentCallBack()
    {
        var response = _momoService.PaymentExecuteAsync(HttpContext.Request.Query);
        return View(response);
    }

    Testing

    Ok cùng mình test nhé các bạn. Giao diện thì như mọi khi. Rất chi là đơn giản laugh

    đâs

    #Quan trọng: Các bạn nhớ đọc kỹ các mục trên để có thể tải App MoMo Test và tạo Tài Khoản Test nhé

    Sau khi nhấn Thanh Toán sẽ được chuyển tới trang thanh toán của MoMo. Tại đây thì các bạn mở App MoMo Test lên mà Quét Mã thôi

    đâs

    Và kết quả chúng ta nhận được sau khi thực hiện thanh toán

    dá

    đá

    Với dữ liệu được trả về thành công các bạn có thể lưu nó xuống bất kỳ đâu các bạn muốn ví dụ như Database hoặc Excel tùy các bạn.

    Tạm kết

    Vậy là mình đã hướng dẫn xong rồi. Nếu thấy hay thì cho mình một share nhé.

    À gặp vấn đề gì các bạn comment bên dưới mình sẽ cố gắng giải đáp cho các bạn!

    Cám ơn các bạn đã theo dõi 😘


    Tiểu sử
    Are you one or zero?


    Bình luận