【问题标题】:I'm trying to validate the callback send to my website in php我正在尝试在 php 中验证发送到我的网站的回调
【发布时间】:2022-09-23 23:25:00
【问题描述】:

我正在尝试用 php 验证发送到我网站的回调。

请我尝试使用此 api 文档https://support.cryptapi.io/article/how-to-verify-the-callback-signature 来验证发送到我的网站的回调,但我的代码一直向 api 显示错误

我不知道它是否来自我的代码

<?php


$pubkey = 
\"-----BEGIN PUBLIC KEY-----\\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3FT0Ym8b3myVxhQW7ESuuu6lo\\ndGAsUJs4fq+Ey//jm27jQ7HHHDmP1YJO7XE7Jf/0DTEJgcw4EZhJFVwsk6d3+4fy\\nBsn0tKeyGMiaE6cVkX0cy6Y85o8zgc/CwZKc0uw6d5siAo++xl2zl+RGMXCELQVE\\nox7pp208zTvown577wIDAQAB\\n-----END PUBLIC KEY-----\";       


$signature = base64_decode($_SERVER[\'HTTP_X_CA_SIGNATURE\']);
$algo = OPENSSL_ALGO_SHA256;

// if request is GET
$data = \"https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]\";

// if request is POST
$data = file_get_contents(\'php://input\');

if (openssl_verify($data, $signature, $pubkey, $algo) == 1) {



require \"cryptapi.php\";
$url = $_GET[\'userdata\'];

$postdata = CryptAPI\\CryptAPI::process_callback($_GET);
$amount = $postdata[\'value_coin\'];
$txid_in = $postdata[\'txid_in\'];

$data = array(
    \'amount\' => $amount,
    \'txid_in\' => $txid_in
);

$payload = json_encode($data);

// Prepare new cURL resource
$ch = curl_init(urldecode($url));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

// Set HTTP Header for POST request 
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    \'Content-Type: application/json\',
    \'Content-Length: \' . strlen($payload))
);

// Submit the POST request
$result = curl_exec($ch);

// Close cURL session handle
curl_close($ch);

echo \"*ok*\";


} else {
echo \"error\";
    // signature NOT valid
}
?>
  • 它应该显示好的到那个api
  • 究竟是什么错误?
  • 它应该显示 echo ok 而不是错误
  • 所以你是说openssl_verify 返回了假?
  • 我不太了解 openssl_verify

标签: php


【解决方案1】:

首先,如果手动运行,请确保您的回调 URL 可以在付款后成功执行操作,例如 https://example.com/verifypayment.php?order_id=908978675650&username=somebody&prod_id=200&amount=500&email=somebody@gmail.com&logticker=trc20_usdt 添加您可能需要的任何 getter ($_GET) 或 setter ($_POST) 作为参数,但请确保有一个唯一的参数来区分订单。在上面的 URL 中,我的唯一参数是 order_id 我的代码在verifypayment.php 中是这样的

    if(isset($_GET['order_id']) && isset($_GET['email']) && isset($_GET['amount']) && isset($_GET['logticker'])){
    $id = intVal($_GET['order_id']);
    $email = $_GET['email'];
    $logticker = $_GET['logticker'];//ENSURE YOU USE THE APPROPRIATE TICKER  https://cryptapi.io/cryptocurrencies/. SETTING TICKER AS PART OF YOUR  PARAMETERS MAKES THE USAGE OF DIFFERENT COIN TICKERS DYNAMIC AND FLEXIBLE
    $data = str_replace("@","%40",$data);//PLS ADD THIS LINE OF CODE IF EMAIL IS INCLUDED IN YOUR PARAMETERS TOO LIKE MINE CUZ CRYPTAPI SAVES @ IN ITS URLENCODE (%40)

    $query = array(
        "callback" => trim($data)
    );
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => "https://api.cryptapi.io/" . $logticker . "/logs/?" . 
        http_build_query($query),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => "GET",
    ]);
    $response = curl_exec($curl);
    $error = curl_error($curl);
    curl_close($curl);        
    if ($error) {
        //echo "cURL Error #:" . $error; OR
        error_log("cURL Error #:" . $error,0);
    } else {
        //echo $response;
        $j = json_decode($response); 
        if(strcmp($j->status,"success")==0){//COMMAND EXECUTED SUCCESSFULLY IF APPROPRIATE URL IS CALLED
            $callbacks = $j->callbacks;//ARRAY OF DEPOSITS MADE INTO THE ADDRESS_IN
            if(is_array($callbacks)){
                $trans = count($callbacks);//NUMBER OF DEPOSITS MADE INTO THE ADDRESS_IN
                if($trans > 0){//IF ANY DEPOSIT IS MADE
                    $totalCoinDeposited = 0; $last_update = ''; $last_uuid = ''; $forwarded_amount = 0;
                    for($i = 0;$i < $trans;$i++){
                        $pending = intVal($callbacks[$i]->pending);
                        if($pending == 0){//IF DEPOSIT HAS BEEN CONFIRMED, IT S NO MORE PENDING
                            $value_coin = doubleVal($callbacks[$i]->value_coin);
                            $totalCoinDeposited += $value_coin;//GET THE SUM OF COIN SENT TO THE ADDRESS_IN
                            $last_update = $callbacks[$i]->last_update;
                            $last_uuid = $callbacks[$i]->uuid;
                            echo "TRANSACTION$i CONFIMRED<BR />";
                        }
                        if(strcmp($callbacks[$i]->result,"sent")==0){//IF DEPOSIT MADE HAS BEEN REMITTED INTO ADDRESS_OUT (YOUR OWN ADDRESS)
                            $forwarded_amount += doubleVal($callbacks[$i]->value_forwarded_coin);
                        }
                    
                    }
                    if($totalCoinDeposited >= doubleVal($_GET['amount'])){//IF TOTAL COIN SENT TO THE ADDRESS_IN IS UP TO THE AMOUNT EXPECTED
                        //YOUR CODES HERE WHEN THE TRANSACTION IS CONFIRMED SUCCESSFUL
                    }
                }
                else{
                    //echo "No deposit yet";
                    //error_log("No deposit yet",0);
                }
            }
                    
        }
        else{
            //echo "Callback URL not found";
            error_log("Callback URL not found",0);
        }

    }
            
}

【讨论】:

    【解决方案2】:

    先忽略openssl_verify函数,使用php curl函数https://docs.cryptapi.io/#operation/logs 这就是我为实现我的期望所做的事情

    【讨论】:

      【解决方案3】:

      CryptAPI\CryptAPI::process_callback($_GET) 对我不起作用,我使用了https://docs.cryptapi.io/#operation/logs 提供的 php curl

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      • CryptAPI\CryptAPI::process callback($GET) 对我也不起作用。如果您可以按照我发布的流程进行操作,则可以
      【解决方案4】:

      我忘了补充。在我自己的情况下,我的服务器 MOD_SECURITY 不允许他们的 webhook 从他们的一端运行回调 url,所以我使用 CRON 来自动运行它。 确保每个订单的回调 url 也存储在订单表中。必须有一个名为 order_confirmed 的列或您可以给它的任何名称。让您的 CRON 通过 SQL 查询循环未确认的 callback_url,例如“SELECT callback_url FROM order_table WHERE order_confirmed = 0”

      //Before your SQL while loop
      $urls = array();
      //In your query while loop
      while(...){
          $urls[] = $callback_url; // WHERE $callback_url IS THE CALLBACK URL (VALUE) THAT COMES FROM THE COLUMN THAT STORES THE CALLBACK URL FOR AN ORDER
      }
      
      //After your query while loop
      
      $curlMultiReq = curl_multi_init();
      $ch = [];
      foreach($urls as $key => $url){
          $ch[$key] = curl_init($url);
          curl_setopt($ch[$key], CURLOPT_HEADER, true);    // we want headers              
          curl_setopt($ch[$key], CURLOPT_NOBODY, true);    // we don't need body
          curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER,1);
          curl_setopt($ch[$key], CURLOPT_TIMEOUT,10);
          curl_multi_add_handle($curlMultiReq, $ch[$key]);
      }
      $running = '';
      do {
          curl_multi_exec($curlMultiReq, $running);//THIS EXECUTES OR RUNS EACH CALLBACK URL AT THE BACKGROUND
          curl_multi_select($curlMultiReq);
      } while ($running > 0);
      foreach(array_keys($ch) as $key){
          //echo curl_getinfo($ch[$key], CURLINFO_HTTP_CODE);
          //echo "\n";  
          curl_multi_remove_handle($curlMultiReq, $ch[$key]);
      }
      curl_multi_close($curlMultiReq);
      

      如果交易成功,请确保您的 CALLBACK_URL 更新 order_confirmed 为 1,这样成功的交易将不会再次循环

      【讨论】:

      • Stackoverflow 不是论坛。请不要针对同一个问题发布多个不同的答案(除非他们针对该问题提供不同的、相互竞争的解决方案)。如果需要您所有的答案来解决问题,那么请将它们合并为一个答案。另请参阅tourHow to Answer 以了解有关此站点如何工作的更多信息 - 这是一种问答形式,而不是线性讨论。谢谢。
      猜你喜欢
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-23
      • 2017-06-21
      相关资源
      最近更新 更多