Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Developer
Posts: 368
Registered: ‎06-30-2012
My Device: Playbook, Z10LE, DevAlpha C
My Carrier: Telenor, Mobitel

QT and Payment API question

I have problems to integrate Payment API (in app payments) in my QT QML Application.

Problem is, that when i instantiate Payment API , i can't see dialogs for purchasing goods, QT view is over them. Code which instantiate payments works OK when i call it from normal native app. When i put it inside QT app, i cant never seen dialog for confirming payments. However, i can see, dialog which prompts user to login on APPWorld which is first presented to user, but after that should be displayed confirmation purchase dialog, and it goes somehov below QT, not over.

I tried to search Cascades forum and samples , but nothing found regarding in app payments.

Anybody have some suggestion?

Thx

Developer
Posts: 368
Registered: ‎06-30-2012
My Device: Playbook, Z10LE, DevAlpha C
My Carrier: Telenor, Mobitel

Re: QT and Payment API question

Anyone?

I tried changing z order to higher number in  screen_set_window_property_iv and i manage to get purchase window over Qt window, but when i destroy that screen , somehow all events not working anymore. I cant use even system events (navigator) and usually i need to restart PB. 

Retired
Posts: 329
Registered: ‎05-07-2012
My Device: BB Alpha
My Carrier: N/A

Re: QT and Payment API question

Hi there,

 

Could you provide the classesa you are using and snippets on how you instantiate your dialogs?

 

Martin

Developer
Posts: 368
Registered: ‎06-30-2012
My Device: Playbook, Z10LE, DevAlpha C
My Carrier: Telenor, Mobitel

Re: QT and Payment API question

Sure

This is code which is called from QML (when button is pressed):

int nativeWrapper::cppMethod(){
    purchasesms *ps = new purchasesms();


         if (ps->setup_screen() != EXIT_SUCCESS) {
               return -1;
            }

         char* sku = (char *)"prcGoodsXm5";

              purchase_outcome p = ps->purchase_credit(sku);

              delete ps;
              return p.errorId;

}

  this is my purchasesms.h header

/*
 * purchasesms.h
 *
 *  Created on: 15. jul. 2012
 *      Author: zeljko
 */

#ifndef PURCHASESMS_H_
#define PURCHASESMS_H_
#include <bps/bps.h>
#include <bps/paymentservice.h>
#include <bps/navigator.h>
#include <screen/screen.h>
#include <stdio.h>
#include <stdlib.h>

struct purchase_outcome {

    int errorId;//0 OK, 1 error request, 2 cancel, 3 other

    const char *errorText;
    //if successfull key of payment
    const char *key;


};
typedef struct purchase_outcome purchase_outcome;


class purchasesms {
public:
	purchasesms();
	virtual ~purchasesms();
	int setup_screen();

	purchase_outcome purchase_credit(char* sku);

private:
	char* get_window_group_id();

	int fail();
	void cleanup();

};

#endif /* PURCHASESMS_H_ */

 and this is purchasesms.cpp class, as you can see, first i call setup_screen() method to prepare screen, i tried even to modify get_window_group_id() method by passing it Qapplication:aplicattionid instead of getpid() but same result:

/*
 * purchasesms.cpp
 *
 *  Created on: 15. jul. 2012
 *      Author: zeljko
 */

#include "purchasesms.h"
	static screen_context_t screen_ctx;
	static screen_window_t screen_win;
purchasesms::purchasesms() {




}


purchase_outcome purchasesms::purchase_credit(char* digital_good_sku) {
	bps_initialize();
		paymentservice_request_events(0);           // 0 indicates that all events
		                                            // are requested

        paymentservice_set_connection_mode(true);   // Allows local testing
		//const char* digital_good_id = "";//we are finding goods with sku name



		const char* purchase_app_icon =
		    "http://www.rim.com/products/appworld_3col.jpg";
		const char* purchase_app_name = "Test purchase";

		unsigned request_id = 0;


		 if (paymentservice_purchase_request(NULL, digital_good_sku, NULL,
		            NULL, purchase_app_name, purchase_app_icon, get_window_group_id(), &request_id) != BPS_SUCCESS) {
		        fprintf(stderr, "Error: purchase request failed.\n");

		        cleanup();
		        purchase_outcome fb = { 1, (char *)"Error in request", (char *)"" };
		        return fb;

		    }
		   bps_event_t *event = NULL;
		        bps_get_event(&event, -1);

		        if (event) {

		            /*
		             * If it is a Payment Service event, determine the response code
		             * and handle the event accordingly.
		             */
		            if (bps_event_get_domain(event) == paymentservice_get_domain()) {
		                if (SUCCESS_RESPONSE == paymentservice_event_get_response_code(event)) {
		                    if (PURCHASE_RESPONSE == bps_event_get_code(event)) {
		                    	 const char* date = paymentservice_event_get_date(event, 0);
		                    	    const char* digital_good = paymentservice_event_get_digital_good_id(event, 0);
		                    	    const char* digital_sku = paymentservice_event_get_digital_good_sku(event, 0);
		                    	   const char* license_key = paymentservice_event_get_license_key(event, 0);
		                    	    const char* metadata = paymentservice_event_get_metadata(event, 0);
		                    	    const char* purchase_id = paymentservice_event_get_purchase_id(event, 0);

		                    	    fprintf(stderr, "Purchase success. Request Id: %d\n Date: %s\n DigitalGoodID: %s\n SKU: %s\n License: %s\n Metadata: %s\n PurchaseId: %s\n\n",
		                    	        request_id,
		                    	        date ? date : "N/A",
		                    	        digital_good ? digital_good : "N/A",
		                    	        digital_sku ? digital_sku : "N/A",
		                    	        license_key ? license_key : "N/A",
		                    	        metadata ? metadata : "N/A",
		                    	        purchase_id ? purchase_id : "N/A");

		                    	    	cleanup();

		                    	    	 purchase_outcome fb = { 0, (char *)"", (char *)license_key };
                                         return fb;
                                }
		                //should not happen here

		                } else {

		                	 int error_id = paymentservice_event_get_error_id(event);
		                	    const char* error_text = paymentservice_event_get_error_text(event);

		                	    fprintf(stderr, "Payment System error. Request ID: %d  Error ID: %d  Text: %s\n",
		                	            request_id, error_id, error_text ? error_text : "N/A");
		                	    cleanup();

		                	    if(error_id == 1) {
		                	    	 purchase_outcome  fb = { 2, (char *)error_text , (char *)"" };
		                	    	 return fb;
		                	    }
		                	    else {
		                	    	 purchase_outcome  fb = { 3, (char *)error_text, (char *)"" };
		                	    return fb;

		                	    }

		                }
		            }
		        }


		        cleanup();
		        purchase_outcome fb = { 3, (char *)"Unknown error", (char *)"" };
		        return fb;
}
void purchasesms::cleanup(){
	 bps_shutdown();
			         screen_destroy_window(screen_win);
			         screen_destroy_context(screen_ctx);



}
purchasesms::~purchasesms() {

}
char *
purchasesms::get_window_group_id()
{
	static char s_window_group_id[16] = "";

	    if (s_window_group_id[0] == '\0') {
	        snprintf(s_window_group_id, sizeof(s_window_group_id), "%d", getpid());
	    }

	    return s_window_group_id;
}

int
purchasesms::fail()
{
	  screen_destroy_window(screen_win);
	    screen_destroy_context(screen_ctx);
	    return EXIT_FAILURE;

}
int
purchasesms::setup_screen()
{


	 const int usage = SCREEN_USAGE_NATIVE;

	    screen_context_t screen_ctx;
	    screen_window_t screen_win;
	    screen_buffer_t screen_buf = NULL;
	    int rect[4] = { 0, 0, 0, 0 };

	    /* Setup the window */
	    if (screen_create_context(&screen_ctx, 0) != 0) {
	           return EXIT_FAILURE;
	       }

	    if (screen_create_window(&screen_win, screen_ctx) != 0) {
	            screen_destroy_context(screen_ctx);
	            return EXIT_FAILURE;
	        }

	    if ( screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0)
	        	 return fail();
        
        //if i dont set this property, payment screen will not show at all
        const int zorder = 10;
        if ( screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &zorder) != 0)
                 return fail();


	    if (screen_create_window_buffers(screen_win, 1) != 0)
	        	 return fail();

	    if (screen_create_window_group(screen_win, get_window_group_id()) != 0)
	    	 return fail();

	    if (screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0)
	        	 return fail();

	    if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2) != 0)
	       	 return fail();


	    /* Fill the screen buffer with blue */
	    int attribs[] = { SCREEN_BLIT_COLOR, 0xff0000ff, SCREEN_BLIT_END };


	    if (screen_fill(screen_ctx, screen_buf, attribs) != 0)
	       	 return fail();

	    if (screen_post_window(screen_win, screen_buf, 1, rect, 0) != 0)
	       	 return fail();


    return EXIT_SUCCESS;


}

 

Code runs ok if it is inside native apllication.

Inside Qt if i dont set z order of window inside setup_screen() method i will not get payment dialogs at all. However, when i set z order, they will become visible, and payment is successful, but after that app is frozen and don't react on any event anymore, and i need to restart Playbook.

 

I know that this could be done with Cascades and foreign window class, but this is application which should be done ASAP and i can't wait January till Cascades should arrive on production.

 

Highlighted
New Developer
Posts: 31
Registered: ‎07-23-2012
My Device: playbook
My Carrier: -

Re: QT and Payment API question

Is there Qt Payment API
Retired
Posts: 329
Registered: ‎05-07-2012
My Device: BB Alpha
My Carrier: N/A

Re: QT and Payment API question

[ Edited ]

Can you confirm which NDK you are uing to build this 2.0?

 

Martin

 

Developer
Posts: 368
Registered: ‎06-30-2012
My Device: Playbook, Z10LE, DevAlpha C
My Carrier: Telenor, Mobitel

Re: QT and Payment API question

Tried with 2.0.0 and 2.0.1, same behaviour.

Retired
Posts: 329
Registered: ‎05-07-2012
My Device: BB Alpha
My Carrier: N/A

Re: QT and Payment API question

Your cleanup() method seems to be called from within when purchase_credit().

It seems that the context of the purchase_credit() would attempt to cleanup the dialog, but the call to cleanup() uses the 'screen_win' variable, which I assume is the screen window ID for more than a popup dialog Is it intended to destroy the entire application context on an error meessage?

 

 

Developer
Posts: 368
Registered: ‎06-30-2012
My Device: Playbook, Z10LE, DevAlpha C
My Carrier: Telenor, Mobitel

Re: QT and Payment API question

[ Edited ]

Yeah, that class is called only when i need in app purchase, rest of app is Qt. I'm using it just to make in app purchase, nothing more, i discard it when i'm done with it. I'm making that screen context just to be able to display in app purchase. This is just my effort to call native window inside Qt app, and in app purchase must attach on some native window to be displayed as dialog on top of it.

 

If you have some other idea how to integrate in app payments into QT application i'm all ears Smiley Happy

Retired
Posts: 329
Registered: ‎05-07-2012
My Device: BB Alpha
My Carrier: N/A

Re: QT and Payment API question

Hmm, I tend to focus on Cascades applications -but lets do a quick test:

 

Before you destroy your dialog, try setting its z order to -10. After the dialog is destroyed and no longer visible, does your app receive messages from the user or is it still frozen? If it does receive messages, it seems to indicate that it still exists and blocks messages from the user;