>

내가 아는 한, IPN/Webhook은 백엔드 알림이며, 프런트 엔드 리턴 URL을 사용할 수 없을 때 판매자 측 시스템이 트랜잭션 업데이트를 안정적으로 수신 할 수 있도록 도와줍니다.

그러나 이것은 개발 중에 경험 한 것이 아닙니다. 프론트 엔드 리턴이 처리되지 않으면 IPN 또는 Webhook이 트리거되지 않습니다. 이로 인해 "백엔드 알림"의 전체 목적이 무효화됩니다.

잘못 입증되고 싶지만 주문/인증/판매로 Omnipay/PaypalSDK의 순열을 테스트했으며 샌드 박스/라이브 환경에서 Webhook/IPN을 기다렸지 만 아무 것도 작동하지 않습니다.

설정은 다음과 같습니다.

  • Omnipay 및 Paypal SDK가 포함 된 Laravel의 HP
  • 포트가 올바르게 전달 된 Docker는 LAN 외부에서 HTTP 및 HTTPS에 액세스 할 수 있습니다
  • Paypal의 REST 앱에서 Webhook을 활성화했습니다. 비즈니스 프로필에서 IPN을 사용하도록 설정
  • 샌드 박스 모드에서 테스트 된 트랜잭션 (판매, 주문, 캡처), 모두 작동 함
  • 테스트 된 Paypal의IPN 시뮬레이터Mock Webhook은 모두 작동했습니다
  • 샌드 박스 및 라이브모드에서주문 및 판매테스트 <올>
  • Paypal 거래를 시작하기 위해 API를 호출하고 리디렉션 URL을 수신함
  • 열린 URL, 로그인, 결제 확인, return_url 로 다시 리디렉션   paymentId 를 포함한 Paypal의 URL 쿼리  그리고 PayerID
    • 현재, return_url  페이지는 URL 쿼리 만 표시하지만 Paypal의콜백 반환을 처리하지 않습니다.
    • 하지 않았습니까 callback_url 에서IPNWebhook을받지 않았습니다. s
    • IPN 조직학페이지 및웹 후크 이벤트페이지하지 마십시오새 이벤트 표시
  • Paypal의반환 콜백을 처리하도록 수정 된 코드 (즉, "/v1/payments/orders/{$this->getId()}/capture" ) ) 및 새로 고침 return_url  페이지.
    • 현재, return_url  성공
    • 인 캡처 상태 및 거래 상태가 페이지에 표시됩니다.
    • 있었습니까 callback_url 에서IPNWebhook을 받음 s
    • IPN 조직학페이지 및Webhook 이벤트페이지새 이벤트 표시

그러면 ... Paypal의 IPN과 Webhook은 모두 백엔드 알림 용이 아니며 프런트 엔드 반품 처리는 필수입니까? 그러나 "안타깝게도 return_url이 사용자의 말에 의해 유발되지 않도록 IPN을 사용해야합니다"등의 주장을하는 사람들을 봤습니다. 뭔가 빠졌거나 잘못 되었습니까?

업데이트-코드 포함

<올>
  • 내 "지불"버튼은 다음 URL로 POST를 보냅니다 : https://*PUB_IP_ADDRESS*/v2/payment/paypal/sale  (와이즈 와이즈)  또는 sale  이 JSON 콘텐츠를 사용하여 해당 작업에 대해) :

    order
    
    

  • 컨트롤러/리포지토리에서 Omnipay 및 PaypalSDK로 테스트했습니다.

    a. Omnipay를 사용하면 다음이 완료됩니다.

    {
        "order_id":"test-23-order",
        "amount":"0.01",
        "currency":"CAD",
        "description":"1753 total .01"
    }
    
    

    // PaymentController.php ... $result = $this->gateway ->setOrderId($request->get('order_id')) ->setAmount($request->get('amount')) ->setCurrency($request->get('currency')) ->setDescription($request->get('description')) ->initPayment(); ...  Omnipay의 Paypal Gateway입니다. 그런 다음

    $this->gateway
    
    

    여기서 // OmnipayRepository.php ... public function initPayment(){ if (is_null($this->payment_intent)){ throw ExceptionMapping(40000, "You need to set payment intent first with setIntent()"); } $payment_params = $this->getPaymentParameters(); switch ($this->payment_intent){ case self::INTENT_PREAUTH: $payment_action = $this->gateway->authorize($payment_params); break; case self::INTENT_SALE: $payment_action = $this->gateway->purchase($payment_params); break; default: throw ExceptionMapping(40000, "{$this->payment_intent} is an invalid payment intent for this action"); } $response = $payment_action->send(); return $this->handleTransactionResponse($response); } ...  반환 된 JSON을 가져 와서 모델에 저장합니다.

    b. Paypal SDK :

    handleTransactionResponse($response)
    
    

    그리고

    // PaymentController.php
    ...
     $paypal = new PaypalRepository();
        $payment = $paypal->initPayment(
            $request->get('amount'),
            $request->get('currency'),
            $request->get('description'),
            URL::to("/").config("paypal.options.returnUrl"),
            URL::to("/").config("paypal.options.cancelUrl"),
            'order',
            $request->get('order_id')
        );
    
        if ($payment['error']) {
            echo $payment['error']."ERR_PP";
        } else {
            $approvalUrl = $payment['payment']->getApprovalLink();
            echo $approvalUrl;
            exit;
        }
    ...
    
    

  • 그런 다음 Paypal은이 JSON으로 응답합니다 :

    // PaypalRepository.php::initPayment()
    ...
        $payment = null;
        $payer = new Payer();
        $payer->setPaymentMethod("paypal");
        $item1 = new Item();
        $item1->setName($descr)
            ->setDescription($descr)
            ->setCurrency($currency)
            ->setQuantity(1)
            ->setSku($sku)// Similar to `item_number` in Classic API
            ->setPrice($total);
        $itemList = new ItemList();
        $itemList->setItems(array($item1));
        $details = new Details();
        $details->setShipping(0);
        $details->setTax(0);
        $details->setSubtotal($total);
        $amount = new Amount();
        $amount->setCurrency($currency);
        $amount->setTotal($total);
        $amount->setDetails($details);
        $transaction = new Transaction();
        $transaction->setAmount($amount);
        $transaction->setItemList($itemList);
        $transaction->setDescription($descr);
        $transaction->setInvoiceNumber(uniqid());
        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl($returnUrl);
        $redirectUrls->setCancelUrl($cancelUrl);
        $payment = new Payment();
        $payment->setIntent($intent);
        $payment->setPayer($payer);
        $payment->setRedirectUrls($redirectUrls);
        $payment->setTransactions(array($transaction));
        $payment->create($this->apiContext);
    
    

  • 그런 다음 { "id":"PAY-4L424927Y2109544NLF2TY2A", "intent":"sale", "state":"created", "payer":{ "payment_method":"paypal" }, "transactions":[ { "amount":{ "total":"0.01", "currency":"CAD" }, "description":"1716 total .01", "related_resources":[ ] } ], "create_time":"2017-07-24T00:16:40Z", "links":[ { "href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/payment\/PAY-4L424927Y2109544NLF2TY2A", "rel":"self", "method":"GET" }, { "href":"https:\/\/www.sandbox.paypal.com\/cgi-bin\/webscr?cmd=_express-checkout&token=EC-0GN55647HU250615H", "rel":"approval_url", "method":"REDIRECT" }, { "href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/payment\/PAY-4L424927Y2109544NLF2TY2A\/execute", "rel":"execute", "method":"POST" } ] } 로갑니다 판매또는주문거래에 대한 승인을 완료하려면 Paypal 계정으로 로그인하십시오.

  • 이제 approval_url 를 통해 데이터를 처리하지 않으면 Paypal이 IPN 또는 Webhook 이벤트를 트리거하지 않는 위의 원래 글 머리 기호 (3) 및 (4)로 돌아갑니다.  트랜잭션을 완료하려면 코드는 다음과 같습니다.

    a. 옴니 페이 :

    return_url
    
    

    b. 페이팔 SDK :

    // PaymentRepository.php, WIP code for callback_return
    ...
    public function callback_return(Request $request)
    {
        $paymentId = $_GET['paymentId'];
        $payerId = $_GET['PayerID'];
        // Once the transaction has been approved, we need to complete it.
        $transaction = $this->gateway->completePurchase(array(
            'payer_id'             => $payerId,
            'transactionReference' => $paymentId,
        ));
        $response = $transaction->send();
        if ($response->isSuccessful()) {
            // The customer has successfully paid.
            echo "PAID";
        } else {
            echo "ERROR";
            // There was an error returned by completePurchase().  You should
            // check the error code and message from PayPal, which may be something
            // like "card declined", etc.
        }
    }
    ...
    
    

  • // paypal_return.php, code snippet on completing transaction ... $paypal = new paypal(); try { $payment = $paypal->executePaypalIntent(get2('paymentId'), get2('PayerID')); } catch (\Exception $e) { $payment = false; } ...
    • 답변 # 1

      페이팔 버튼에서 페이팔 ipn을 전혀 참조하지 않는 것을 알았습니다 ...

      와이즈 비즈

      이것이 내가하는 방법입니다.

      Try adding notify_url

      URL을 버튼이나 리디렉션으로 사용할 수 있습니다. 성공적인 거래로 지불 한 금액을 확인하십시오.

      IPN 코드에서 할 수있는 한 가지는 메일 알림이 실행될 때 메일 알림을 트리거하고 자신에게 $_POST를 보내는 것입니다. 적어도 IPN이 페이지를 방문한 시점을 알고 있습니다. 실행을 중지하는 PHP 오류가 발생하는 경우 맨 위에 추가하십시오. 우편을받은 후 거래가 처리되지 않으면 무언가 잘못되었다는 것을 알고 Paypal의 잘못이 아님

      IPN

      $_CONFIG['cart']['test'] = "1"; // 0 (paypal) | 1 (sandebox)
      $_CONFIG['cart']['return'] = "http://thx.com";
      $_CONFIG['cart']['ipn'] = "http://dev.com/ipn.php";
      if (!$_CONFIG['cart']['test']){
          $_CONFIG['cart']['webscr'] = "https://www.paypal.com/cgi-bin/webscr?"; // paypal
          $_CONFIG['cart']['postback'] = "www.paypal.com";
          $_CONFIG['cart']['paypal'] = "[email protected]";
      }else{
          $_CONFIG['cart']['webscr'] = "https://www.sandbox.paypal.com/cgi-bin/webscr?"; // sandebox
          $_CONFIG['cart']['postback'] = "www.sandbox.paypal.com";
          $_CONFIG['cart']['paypal'] = "[email protected]";
      }
      $grand_total = "9.99";
      // Bouton Paypal
      $paypalURL .= $_CONFIG['cart']['webscr'].'&';
      $paypalURL .=  'item_name=ITEM NAME&';
      $paypalURL .=  'cmd=_xclick&';
      $paypalURL .=  'business='.urlencode($_CONFIG['cart']['paypal']).'&';
      $paypalURL .=  'return='.urlencode($_CONFIG['cart']['return']).'&';
      $paypalURL .=  'lc=CA&amount='.sprintf("%01.2f", $grand_total).'&';
      $paypalURL .=  'currency_code=CAD&';
      $paypalURL .=  'button_subtype=products&';
      $paypalURL .=  'cn=Ajouter%20des%20instructions%20particuli%c3%a8res%20pour%20le%20vendeur&';
      $paypalURL .=  'no_shipping=2&';
      $paypalURL .=  'shipping=0&';
      $paypalURL .=  'bn=PP%2dBuyNowBF%3abtn_buynowCC_LG%2egif%3aNonHosted&';
      $paypalURL .=  'notify_url='.urlencode($_CONFIG['cart']['ipn']);
      
      

      <?php // read the post from PayPal system and add 'cmd' $req = 'cmd=_notify-validate'; foreach ($_POST as $key => $value) { $value = urlencode(stripslashes($value)); $req .= "&$key=$value"; $mail .= "_POST[$key]: $value<br>"; } // post back to PayPal system to validate $header .= "POST /cgi-bin/webscr HTTP/1.1\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Host: ".$_CONFIG['cart']['postback']."\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n"; $header .= "Connection: close\r\n\r\n"; $fp = fsockopen ('ssl://'.$_CONFIG['cart']['postback'], 443, $errno, $errstr, 30); // Si le fsockopen a fonctionner on poursuit if ($fp) { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (trim($res)=="VERIFIED") { }elseif ($res=="INVALID") { }else{ } } // On ferme la connexion fclose ($fp); }else{ echo "404"; } $subject = "IPN-DEBUG"; $messagez = "Paypal info:<br />$mail<br /><br />$prod_mail"; $de = "[email protected]"; send_mail($subject, $messagez, $de, '[email protected]'); function send_mail($subject, $message, $de, $to){ require_once ('module/phpmailer/MailClass.php');//send_mail $send_mail = new FreakMailer(); $send_mail->Subject = $subject; $send_mail->Body = $message; $send_mail->isHTML(true); $send_mail->From = $de; $send_mail->AddAddress($to); if(!$send_mail->Send()){return 'false';}else{return 'true';} $send_mail->ClearAddresses(); $send_mail->ClearAttachments(); } ?>

  • 이전 python - 프로그램이 파일에서 XML 데이터를 찾을 수 없습니다
  • 다음 vba - 본문 메시지의 마지막 행 범위 텍스트를 넣어 Excel에서 Outlook 전자 메일 보내기