Lỗi sai chữ ký khi thanh toán vnpay?

Chào mọi người em có đang thử thích hợp cái vnpay vào website của mình nhưng mà mãi em vẫn chưa rõ lỗi ở đâu mà cái chữ ký của em nó cứ báo sai. Em dùng hmacsha512 để tạo chữ ký từ cái data mà mình gửi cho vnpay và cái hashscecret mà mình đăng ký. Khi đọc doc của vnpay thì nó bảo cái data mình gửi lên phải sắp xếp theo tăng dần thì em cũng đã thủ công sắp xếp đúng chuẩn tăng dần rồi mà vẫn không được. Thuật toán hmacsha512 thì em có lấy rất nhiều cách trên mạng nhưng vẫn cứ bị báo lỗi là sai chữ ký.Em sẽ để code ở đây nếu ai rảnh thì có thể thử và test giúp em với ạ.Em cảm ơn.

package com.webbansach.service.impl;

import com.webbansach.hmac.Sha512;
import com.webbansach.service.IPaymentVnpayService;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


@Service
public class PaymentVnpayService implements IPaymentVnpayService {

    final String VNP_TMNCODE = "ABC123";
    final static String VNP_HASHSECRET = "XYZ789";
    final String VNP_URL = "https://sandbox.vnpayment.vn/paymentv2/vpcpay.html?";
    final String VNP_VERSION = "2.1.0";
    final String VNP_COMMAND = "pay";
    final String ORDER_TYPE = "150000";

    private RestTemplate restTemplate;
    private HttpHeaders headers;

    @Override
    public String sendRequest(long orderId1, int totalPrice, HttpServletRequest request) throws Exception {
        restTemplate = new RestTemplate();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        LocalDateTime dateTimeNow = LocalDateTime.now();

        String vnp_Version = VNP_VERSION;
        String vnp_Command = VNP_COMMAND;
        String vnp_OrderInfo = "DH" + dtf.format(dateTimeNow);
        String vnp_OrderType = ORDER_TYPE;
        String vnp_TxnRef = String.valueOf(orderId1);
        String vnp_IpAddr = "127.0.0.1";
        String vnp_TmnCode = VNP_TMNCODE;
        String vnp_BankCode = "NCB";
        String vnp_CreateDate = dtf.format(dateTimeNow);
        String vnp_Amount = String.valueOf(totalPrice * 100);
        String vnp_CurrCode = "VND";
        String vnp_Locale = "vn";
        String vnp_ReturnUrl = "http://localhost:8080/thanh-cong";

        String rawHash = "vnp_Amount=" + vnp_Amount +
//                         "&vnp_BankCode=" + vnp_BankCode +
                         "&vnp_Command=" + vnp_Command +
                         "&vnp_CreateDate=" + vnp_CreateDate+
                         "&vnp_CurrCode=" + vnp_CurrCode +
                         "&vnp_IpAddr=" + vnp_IpAddr +
                         "&vnp_Locale=" + vnp_Locale +
                         "&vnp_OrderInfo=" + vnp_OrderInfo +
                         "&vnp_OrderType=" + vnp_OrderType +
                         "&vnp_ReturnUrl=" + vnp_ReturnUrl+
                         "&vnp_TmnCode=" + vnp_TmnCode +
                         "&vnp_TxnRef=" + vnp_TxnRef +
                         "&vnp_Version=" + vnp_Version;

        Sha512 sha512 = new Sha512();
        String vnp_SecureHash = sha512.calculateHMac(VNP_HASHSECRET, rawHash);

        String urlResult = VNP_URL+rawHash+"&vnp_SecureHash=" + vnp_SecureHash;
        return urlResult;
    }

    
}

cái này nên thử dùng code mẫu của vnpay rồi đối chiếu lại chuỗi data gốc và data đã hash với kết qủa của bạn xem có gì sai hay không
hoặc bạn cũng có thể copy code ra các ngôn ngữ khác để chạy để so sánh, có sẵn code mẫu có 5 ngôn ngữ mà

6 Likes

Bạn đã fix được lỗi này chưa ạ? có thể chỉ mình với được không

Cái này có mấy khả năng mình đã từng gặp lỗi này (do vnpay bắt lỗi chung chung nên bạn chịu khó kiểm tra nhé)

  1. Thiếu params của vnp_xxx: cái này khả năng xảy ra nhiều nhất, khi đủ params đặc biệt là input trước khi mã hoá và output khi checksum ipn url
  2. Sử dụng khác loại mã hoá ví dụ 256sha nhưng đầu còn lại 128 chẳng hạn
  3. Thứ tự các params trước khi mã hoá
  4. Quá thời gian sử dụng chuỗi mã hoá. Do cơ chế one time nên khi chuỗi dùng rồi dùng lại không được bạn phải trigger lại từ đầu

    Mình cũng gặp một số lỗi liên quan đến proccess FE BE mà vnpay bắt làm theo mới nghiệm thu nữa.

Trên trang chủ cũng có code mẫu vài ngôn ngữ khác nhau bạn tham khảo thử

https://sandbox.vnpayment.vn/apis/docs/huong-dan-tich-hop/#t%E1%BA%A1o-url-thanh-to%C3%A1n

Hi vọng có thể giúp được bạn.

5 Likes

Fix dc chưa bác ơi. Hôm nay làm bị lỗi

Mấy bạn đăng nhập vào hệ thống sửa chuẩn mã hóa lại cho phù hợp với code là chạy ok , mình bị lỗi tương tự và chạy được.

1 Like

sửa ntn vậy ạ? chỉ giúp em với

chỉ rõ giúp em với ạ

Mình cũng đã gặp lỗi này, trong trường hợp của mình thì mình chuyển từ mã hóa SHa56 sang hmacSHA512 thì hết

vị cứu tinh của tui. :heart_eyes: :heart_eyes: :heart_eyes: :heart_eyes: :heart_eyes: :heart_eyes:

NODEJS
Xin chào các bạn!
Mình cũng đã thử tích hợp hình thức thanh toán VNPay cho wesbite của mình sử dụng ExpressJS và mình cũng gặp lỗi “Sai chữ ký - Invalid signature”.
Sau khi fix được lỗi thì mình nhận ra các vấn đề như sau:

  • Sử dụng hàm sortObject có sẵn trong code demo của VNPay (vì nếu tự build sẽ gặp lỗi ngay vì trong hàm sortObject có một chỗ đáng chú ý:
    sorted[str[i]] = encodeURIComponent(obj[originalKey]).replace(/%20/g, "+");
    Vì nếu tự build thì có thể URI chúng ta sẽ có dạng Thanh%20toan%20don%20hang mà không phải là: Thanh+toan+don+hang sai format mà phía VNPay đặt ra nên khi redirect (điều hướng) đến trang thanh toán sẽ bị lỗi.
  • Các bạn nhớ khai báo đầy đủ các tham số được liệt kê trong bảng danh sách tham số ở phần “Tạo URL thanh toán” trên trang vnpayment sandbox. Vì nếu chúng ta không khai báo đầy đủ khi hash(mã hóa) thì sẽ không đảm bảo đầy đủ dữ liệu để tạo signature (chữ kỹ) dẫn đến sai chữ ký.
  • Trong code mẫu có một dòng như thế này:
vnpUrl += '?' + querystring.stringify(vnp_Params, { encode: false }); 

Các bạn nên chuyển encode thành giá trị true để chuyển các ký tự đặc biệt trong url thành dạng phù hợp (khoảng trắng => %20 chẳng hạn)

  • Nếu các bạn đã thử hết mà vẫn chưa fix được, thì có lẽ các bạn còn 1 vài lỗi nhỏ như: kiểm tra giá trị các biến tmnCode,hashSecret để đảm bảo có giá trị đúng. Biến ipAddr chuyển thành định dạng IPV4

Hướng dẫn tích hợp của VNPay:
https://sandbox.vnpayment.vn/apis/docs/thanh-toan-pay/pay.html

Bên trên là những cách mình đã thử để fix lỗi, hi vọng sẽ giúp đỡ anh em fix được lỗi sớm nhé!

Đăng nhập vào kiểm tra chỗ nào bạn

Mình đang làm app e-commerce expressJS API củng bị lỗi như trên, mình đang coi code mẫu và rà soát lại nè huhu :(( . Bị lỗi 2 tuần nay rồi, nản ghê

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?