简体   繁体   中英

I'm trying to validate the callback send to my website in php

I'm trying to validate the callback send to my website in php.

Please I'm trying to use this api documentation https://support.cryptapi.io/article/how-to-verify-the-callback-signature to validate the callback send to my website but my code keep showing error to the api

I don't know whether it from my code

<?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
}
?>

Ignore openssl_verify function first and use php curl function https://docs.cryptapi.io/#operation/logs That's what I did to achieve my expectation

CryptAPI\CryptAPI::process_callback($_GET) did not work for me, I used php curl provided at https://docs.cryptapi.io/#operation/logs

Firstly, ensure your callback URL can successfully execute action after payment if run manually eg https://example.com/verifypayment.php?order_id=908978675650&username=somebody&prod_id=200&amount=500&email=somebody@gmail.com&logticker=trc20_usdt Add any getter ($_GET) or setter ($_POST) you may need as paramaters but make sure there is a unique parameter which distinguishes the orders. In the above URL my unique parameter is order_id My codes go like this in the 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);
    }

}
        

}

I forgot to add. In my own case my server MOD_SECURITY did not allow their webhook to run the callback url from their end so I use CRON to auto run it. Ensure the callback url per order is stored in order table as well. There must be a column named order_confirmed or any name you can give it. Let your CRON loop the unconfirmed callback_urls via SQL query Eg "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);

ENSURE YOUR CALLBACK_URL UPDATE order_confirmed TO 1 IF THE TRANSACTION IS SUCCESSFUL SO THAT SUCCESSFUL TRANSACTIONS WONT BE LOOPED AGAIN

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM