Điểm:2

Lưu dữ liệu vào đơn hàng một cách an toàn trong onNotify()

lá cờ jp

Tôi mới sử dụng Drupal và phải tạo một cổng thanh toán ngoài trang web (với Drupal Commerce 2). Tất cả đều hoạt động, nhưng đôi khi không.

Máy chủ của nhà cung cấp dịch vụ thanh toán từ xa gửi yêu cầu thông báo đến máy chủ, về trạng thái của khoản thanh toán, vì vậy tôi có cả hai onReturnonThông báo trong lớp Cổng thanh toán.

Từ onReturn không đảm bảo sẽ được gọi (khách hàng có thể đóng trình duyệt, v.v. và nhà cung cấp không nhất thiết phải gửi lại cho anh ta trong trường hợp của tôi), nhưng onThông báo được đảm bảo để được gọi, tôi tạo và lưu Sự chi trả đối tượng trong onThông báo, không ở onReturn, khi thanh toán xong. (Đây cũng là những gì tài liệu gợi ý để làm: https://docs.drupalcommerce.org/commerce2/developer-guide/payments/create-payment-gateway/off-site-gateways/handling-ipn)

Vì vậy, mã của tôi trông giống như thế này. (Đó là một mã giả rất đơn giản; kiểm tra xác thực không được bao gồm.)

class RedirectCheckout extends OffsitePaymentGatewayBase implements SupportsNotificationsInterface {

  hàm công khai onReturn() {
    $is_order_accepted = /* Kiểm tra nhà cung cấp dịch vụ thanh toán từ xa đã chấp nhận đơn đặt hàng */
    nếu (!$is_order_accepted) {
       ném NeedsRedirectException() mới
    }
    // Nếu tất cả đều tốt, không làm gì cả.
  }

  hàm công khai onNotify() {
    /** @var OrderInterface $order */
    $order = /* Tải đơn hàng sắp có thông báo */

    $is_order_accepted = /* Kiểm tra nhà cung cấp dịch vụ thanh toán từ xa đã chấp nhận đơn đặt hàng */
    nếu ($is_order_accepted) {
      $thanh toán = $payment_storage->create();
      $thanh toán->lưu();
      $order->setData('transaction_id', $transactionId);
      $order->save(); // Đây là những gì đôi khi bị ghi đè bởi onReturn(), tôi tin vậy.
    }
  }
}

Lưu ý rằng tôi cần lưu một số dữ liệu về đơn hàng, khi đơn hàng được chấp nhận (không có sẵn khi đơn hàng được tạo, chỉ khi thanh toán thành công).
Tài liệu Drupal Commerce nói rằng bạn "không cần (và không nên)" chạm vào đơn đặt hàng, nhưng tôi phải lưu một số dữ liệu bổ sung về đơn đặt hàng mà các bộ phận khác trên hệ thống dự kiến ​​sẽ có ở đó.

Điều này thường hoạt động. Tuy nhiên, hai onReturnonThông báo các yêu cầu từ máy chủ từ xa đôi khi đến gần như cùng một lúc, điều mà tôi tin rằng sẽ dẫn đến tình trạng chạy đua.

Thật không may, mặc dù tôi không làm gì với thứ tự trong onReturn, Thương mại dường như vẫn giữ trật tự. Tôi tin rằng điều này đôi khi có thể ghi đè dữ liệu được lưu vào đơn đặt hàng bởi onThông báo. Ví dụ:

  • onReturn bắt đầu chạy và tải đơn đặt hàng (Việc này do chính thư viện thương mại thực hiện nên tôi không thể làm gì về việc này.)
  • Yêu cầu thông báo đến, vì vậy onThông báo bắt đầu chạy, tải và lưu đơn đặt hàng, rồi trả về
  • Sau này, các onReturn phương thức trả về, trả lại quyền kiểm soát cho Commerce, giúp lưu lại đơn đặt hàng; vì nó đã tải đối tượng đặt hàng trước đó onThông báo đã lưu nó, nó ghi đè lên bất cứ điều gì onThông báo đã viết với dữ liệu cũ

(Có lẽ thứ tự ngược lại cũng có thể có vấn đề, trong đó onThông báo có thể ghi đè bất kỳ dữ liệu nào được Drupal Commerce lưu vào đơn đặt hàng ở hậu trường, nếu có, trong quá trình onReturn yêu cầu.)

Có cách nào tốt để xử lý việc này không, ví dụ như giải quyết vấn đề về điều kiện chủng tộc để có thể lưu dữ liệu đơn hàng vào onThông báo?

Tôi đang sử dụng Drupal 8.6.

Gabriel Fernandez avatar
lá cờ cn
Bạn đã thử sử dụng các sự kiện, chẳng hạn như `commerce_order.place.post_transition` chưa?
lá cờ jp
Ý tưởng thú vị - tôi sẽ xem xét cách nó hoạt động
lá cờ jp
Gợi ý tốt! Thật không may, theo thử nghiệm của tôi, onNotify() không tự đặt hàng (vì vậy sự kiện này không được kích hoạt), khi thanh toán được thêm vào.Vì vậy, cách duy nhất để đặt hàng trong onNotify(), là "áp dụng quá trình chuyển đổi" cho đơn hàng và sau đó tự lưu đơn hàng - nhưng thật không may, sau đó chúng ta quay lại vấn đề tương tranh ở trên, vì cả onNotify() và onReturn() lưu đơn đặt hàng. (Và tôi đoán chúng ta cũng sẽ quay lại vấn đề đó, nếu thương mại tự đặt hàng)
Điểm:1
lá cờ cn

Bạn đúng về điều kiện cuộc đua, nhưng onReturn hoàn toàn không sửa đổi thứ tự

Đây là những gì xảy ra trong nền:

  • các commerce_payment.checkout.return lộ trình thanh toán thương mại mô-đun được gọi mà lúc đầu nó cho phép đặt hàng plugin cổng thanh toán để tạo thanh toán cho đơn hàng
  • thì bất kể điều gì xảy ra trong phương thức onReturn của luồng kiểm tra đơn đặt hàng plugin sẽ được chuyển hướng sang một giai đoạn khác (nếu onReturn ném ngoại lệ, nó sẽ được chuyển hướng đến giai đoạn trước, nếu không nó sẽ được chuyển hướng sang giai đoạn tiếp theo)
  • trong tình huống này phương pháp chuyển hướng sang bước bên trong Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowBase sẽ sửa đổi và lưu thứ tự, đó là nơi xảy ra sự cố.

đây là việc thực hiện chuyển hướng sang bước:

/**
 * {@inheritdoc}
 */
chức năng công cộng redirectToStep($step_id) {
  if (!$this->isStepVisible($step_id)) {
    ném \InvalidArgumentException mới(sprintf('ID bước không hợp lệ "%s" được chuyển tới redirectToStep().', $step_id));
  }

  $this->order->set('checkout_step', $step_id);
  $this->onStepChange($step_id);
  $this->order->save();

  ném NeedsRedirectException mới(Url::fromRoute('commerce_checkout.form', [
    'commerce_order' => $this->order->id(),
    'bước' => $bước_id,
  ])->toString());
}

vì vậy để giải quyết vấn đề trong phương thức onReturn của bạn, bạn nên chờ các thay đổi onNotify được thực hiện (một vòng lặp while đợi cho đến khi các thay đổi theo thứ tự được đặt)

hy vọng nó sẽ giúp.

lá cờ jp
Cảm ơn câu trả lời tốt của bạn! Tuy nhiên, có một câu hỏi - ngay cả khi tôi trong onReturn đợi các thay đổi onNotify được thực hiện, thì "$this->order" có còn chứa các giá trị cũ từ trước khi chạy onNotify không? (vì vậy redirectToStep sẽ lưu các giá trị cũ). Nếu vậy, có cách nào để tải lại "$this->order" trong onReturn (sau khi chờ đợi) không?
lá cờ jp
(Hừm...Và không thể lưu đơn hàng trong onNotify thực sự hoàn nguyên thay đổi thành "checkout_step" theo đơn hàng đã thực hiện, nó chuyển hướngToStep về giá trị cũ?)
Alireza Tabatabaeian avatar
lá cờ cn
Thực ra tôi không chắc lắm về tình huống này nhưng tôi đoán cách này sẽ hiệu quả. Ok, hãy thử xem và nếu mọi thứ không suôn sẻ thì chúng ta có thể nghĩ về các cách tiếp cận khác

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.