Dynamic Payment Buttons/Links

In this tutorial, we will understand how to programmatically create/modify payment buttons. We will also learn how to pass extra data to button and retrieve it in the order information

Resources

Source Code https://github.com/blockonomics/Programming_Bitcoin_Payment_Buttons
Youtube Videohttps://www.youtube.com/watch?v=-FYwR1RzjXY

Tech Stack

  • PHP
  • HTML/CSS
  • Blade

Setting Up

The entire code for this demo is available on Github and you can fork it here. The step by step instructions on how to set up the demo is provided in the README.

What is Programming Bitcoin Payment Buttons/Links?

Blockonomics provide high flexibility when it comes to configuration. The Payment Links or Buttons which you create from your Merchant Page can be programmatically customized to change values for certain parameters like

  • Product Name
  • Product Description
  • Value (Price of the Product)

This modified payment button/link, which you create programmatically is called a child product. Please refer to the documentation for more details. In this tutorial, we will customize the above-mentioned parameters to create child products with new prices (prices after applying some offer/coupon).

Adding Custom Data with the transaction

Blockonomics not only provides the ability to modify existing values for given parameters but also allows you to collect additional information with each transaction. This is passed as extra_data to the transaction. We will look at how to pass real-time information with the transactions in this tutorial. Real-time information can be anything like the product-specific details, the user-specific details, or anything else. In this demo, we are going to pass the color of the iPhone that the user wants to buy.

The Demo

In this demo, we are having a mobile shop where we are offering three different types of iPhones. Each iPhone has a default price and once you click on any of them to make a purchase, you are provided with few options like the color you want to buy and the offer you want to apply. Now, depending on the offer you choose, the price of the product will vary. We are going to use the concept of child products to calculate the new price and create a payment link for the same. The custom data that we are going to pass will contain the offer which buyer chooses and also the color of the iPhone (we don’t want to ship an iPhone of the wrong color!).

Let us look at the Code

Creating Routes

If you navigate to routes/web.php, you can see we have created some routes for this demo.

Route::get('/', 'PageController@home')->name('index');

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::post('/new', 'HomeController@handle')->name('new_link');
Route::get('/history', 'HomeController@track')->name('track');
Route::get('/receive', 'WebhookController@handle');

The /new route is responsible for generating a child product payment link. The /receive route is responsible for getting callbacks from blockonomics. It is the ORDER HOOK URL endpoint.

Logic For Creating Child Product

If you navigate to the corresponding handle function in the HomeController, you can find out the logic. As this is a POST request from the frontend, we receive details about the transaction, like the product, the default price, the offer that the buyer chooses, and the color of the product. Then, depending on the offer we calculate the offered price.

public function handle(Request $request){

        $product = $request->product;
        $price = (int)$request->value;
        $offer = $request->offer;
        $color = $request->color;
        $offered_price = $price;

        if($offer == '1'){
            $offered_price = max(0.75*$price, $price-75);
        }
        else if($offer == '2'){
            $offered_price = $price - 50;
        }
        else if($offer == '3'){
            $offered_price = 0.9*$price;
        }

The next step is to figure out the custom data which you need to pass. We pass the offer number and color of the product as custom data.

$data = array(
            "offer"=>$offer,
            "color"=>$color,
        );

The next step is to call the blockonomics create_child_product API. We pass the parent_uid (uid of the parent is the uid of product which you create from the merchant page) along with other parameters which we wish to modify in the child product. In the response, we get the uid of the child product. This uid can be appended in front of https://www.blockonomics.co/pay-url/ to create a payment link or can be added to the payment button. We then pass the response to the front end with offered_price and the payment link.

        $client =  new Client();
        $response = $client->post('https://www.blockonomics.co/api/create_child_product',[
            'headers'=>['Authorization'=> 'Bearer '.env('Blockonomics_API','')],
            'json' => ['parent_uid' => $parent_uid, 'product_name' => $product, 
            "value" => $offered_price, "extra_data" => (string)json_encode($data)],
        ]);

        $resp = json_decode($response->getBody());
        $data_string =json_encode($resp);
        error_log($data_string);

        $response = array(
            'link' => 'https://www.blockonomics.co/pay-url/'.$resp->uid,
            'price' => $offered_price,
        );
        return response()->json($response);

Order Hook URL Endpoint Logic

Blockonomics hits the endpoint with a GET request, passing the Bitcoin address and the status of the transaction carried using the given address.
We can use the Get Order API to know the details about the user who used the given bitcoin address to perform the transaction. Email can be used as a source of identification but you can pass any logic as you like. Here, we identify the user using the email and update the status or create a new transaction inside database of that user with the one that Blockonomics provided.

class WebhookController extends Controller
{
    public function handle(Request $request){

        $address = $request->addr;
        $status = $request->status;
        try{
            $client =  new Client();
            $response = $client->get('https://www.blockonomics.co/api/merchant_order/'.$address,[
                'headers'=>['Authorization'=> 'Bearer '.env('Blockonomics_API','')],
            ]);

            $data = json_decode($response->getBody());
            $data_string =json_encode($data);
            error_log($data_string);
           
            $product_name = $data->name;
            $price = $data->value;
            $mail = $data->data->emailid;
            $extra_data = json_decode($data->data->extradata);
            $color = $extra_data->color;
            
            $user = User::where('email','=',$mail)->first();

            if(Transaction::where('address','=',$address)->count()){
                $object = Transaction::where('address','=',$address)->first();
                $object->status = (string)$status;
                $user->transactions()->save($object);
            }
            else{
                $object = new Transaction();
                $object->address = $address;
                $object->offered_price = $price;
                $object->color = $color;
                $object->status = (string)$status;
                $object->product_name = $product_name;
                $user->transactions()->save($object);
            }
        }
        catch (\Exception $e){
            error_log($e);
        }

    }
}