前言

团队介绍

作者:徐庆

团队:坚果派 大众号:“大前端之旅” 润开鸿生态技术专家,华为HDE,CSDN博客专家,CSDN超级个别,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发。欢迎协作。

效果图 :

ArkUI-X和原生交互调用Google内购付出

ArkUI-X和原生交互调用Google内购付出

完成办法

咱们是经过AkrUi-X和安卓交互 然后在原生安卓里边参加了内购付出结算库的依靠 最终调起的Google 付出 安卓原生内购付出教程

ArkUI端代码

akrui 端我这边只写了一个按钮调用Google内购付出和接纳数据

ArkUI-X和原生交互调用Google内购付出

导入渠道桥接模块

// 导入渠道桥接模块
import bridge from '@arkui-x.bridge';

创立渠道桥接目标

  // 创立渠道桥接目标
  private bridgeImpl = bridge.createBridge('Bridge');

// 发送数据到Android侧,并经过状态变量,将Android侧的呼应数据显示在页面上
    this.nativeResponse = await this.bridgeImpl.sendMessage('Hello ArkUI-X!');

接回收传回来的数据

  aboutToAppear() {
    this.getHelloArkUI();
  }
  getHelloArkUI() {
    // 调用Android侧办法
    this.bridgeImpl.callMethod('getHelloArkUI').then((result: string) => {
      // 经过状态变量,将Android侧办法的返回值显示在页面上
      this.helloArkUI = result;
    });

完整代码

// 导入渠道桥接模块
import bridge from '@arkui-x.bridge';
@Entry
@Component
struct Index {
  // 创立渠道桥接目标
  private bridgeImpl = bridge.createBridge('Bridge');
  @State helloArkUI: string = '';
  @State nativeResponse: string = '';
  aboutToAppear() {
    this.getHelloArkUI();
  }
  getHelloArkUI() {
    // 调用Android侧办法
    // this.bridgeImpl.callMethod('getHelloArkUI').then((result: string) => {
    //   // 经过状态变量,将Android侧办法的返回值显示在页面上
    //   this.helloArkUI = result;
    // });
/*    this.bridgeImpl?.callMethod('getHelloArkUI').then((data)=>{
    });*/
    // let resultPromise=this.bridgeImpl.callMethod('getHelloArkUI'):resultPromise.then((data)=>{
    //
    //
    //
    //   })
  }
  build() {
    Row() {
      Column() {
        Text(this.helloArkUI)
          .fontSize(15)
          .margin(10)
        Button('点击Google付出')
          .fontSize(15)
          .margin(10)
          .onClick(async () => {
            // 发送数据到Android侧,并经过状态变量,将Android侧的呼应数据显示在页面上
             await this.bridgeImpl.sendMessage('Hello ArkUI-X!');
          })
        Text('Response from Native: ' + this.nativeResponse)
          .fontSize(15)
          .margin(10)
      }
      .width('100%')
    }
    .height('100%')
  }
}

安卓部分

咱们编译项目 需求导入arkui-x编译之后发生的安卓原生宿主工程

ArkUI-X和原生交互调用Google内购付出

官方文档地址

Google结算库

需求的依靠

def billing_version = "6.0.0"
implementation "com.android.billingclient:billing:$billing_version"

ArkUI-X和原生交互调用Google内购付出

akrui-x 和原生安卓通信交互

引证渠道桥接模块
package com.example.helloworld;
/**
 * 作者:xuqing
 * 时间:2024年04月01日 15:27:31
 * 邮箱:1693891473@qq.com
 * 说明:
 */
import android.app.Activity;
import android.content.Context;
import android.util.Log;
// 引证渠道桥接模块
import ohos.ace.adapter.capability.bridge.BridgePlugin;
import ohos.ace.adapter.capability.bridge.IMessageListener;
public class Bridge extends BridgePlugin implements IMessageListener {
    private static final String TAG = "Bridge";
    private Context context;
    public Bridge(Context context, String name, int id) {
        super(context, name, id);
        this.context=context;
        setMessageListener(this);
    }
    // Android侧办法,供ArkUI侧调用
    public String getHelloArkUI() {
        return "Hello ArkUI!";
    }
    // 注册回调,接纳ArkUI侧发来的数据
    @Override
    public Object onMessage(Object object) {
      //  new EntryEntryAbilityActivity(). initgooglePlay();
        GooglePay.getInstance().toGooglePay((Activity) context,"com.testgame.099");
        Log.e(TAG, "onMessage: "+object.toString() );
        return "java onMessage success";
    }
    @Override
    public void onMessageResponse(Object object) {
    }
}

内购付出初始化

public  void initgooglePlay(Activity context) {
    billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .build();
    if(billingClient!=null){
        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() ==  BillingClient.BillingResponseCode.OK) {
                }
            }
            @Override
            public void onBillingServiceDisconnected() {
            }
        });
    }
}

调用起内购付出

public   void  toGooglePay(Activity context,String productId){
    //  String productId ="xxxx";
    List<QueryProductDetailsParams.Product> productList= new ArrayList<>();
    productList.add(QueryProductDetailsParams.Product.newBuilder()
            .setProductId(productId)
            .setProductType(BillingClient.ProductType.INAPP)
            .build());
    QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().
            setProductList(productList)
            .build();
    if(billingClient!=null){
        billingClient.queryProductDetailsAsync(
                queryProductDetailsParams,
                new ProductDetailsResponseListener() {
                    public void onProductDetailsResponse(BillingResult billingResult,
                                                         List<ProductDetails> productDetailsList) {
                        if(productDetailsList!=null&&productDetailsList.size()>0){
                            ProductDetails productDetails=productDetailsList.get(0);
                            List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList= new ArrayList<>();
                            productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
                                    .setProductDetails(productDetails)
                                    .build());
                            BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                                    .setProductDetailsParamsList(productDetailsParamsList)
                                    .build();
                            billingClient.launchBillingFlow((Activity) context, billingFlowParams);
                        }else {
                            Toast.makeText(context,"产品ID无效",Toast.LENGTH_SHORT).show();
                        }
                    }
                }
        );
    }
}

咱们在arkui-x调用安卓原生的回调办法里边去调用咱们的 toGooglePay 传入咱们的产品ID 即可

  • 付出回调


    private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                    && purchases != null) {
                for (Purchase purchase : purchases) {
                    handlePurchase(purchase);
                    Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                }
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
            } else {
            }
        }
    };

咱们拿到回调里边的 getPurchaseToken getSignature getSignature 信息之后可以去自己服务端进行验签 假如验签成功了才算是真实的成功付出成功 然后再进行耗费

  • 产品耗费

public void handlePurchase(final Purchase purchase) {
    ConsumeParams consumeParams =
            ConsumeParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
                Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                Log.e(TAG, "getSignature: "+ purchase.getSignature() );
            }
        }
    };
    if(billingClient!=null){
        billingClient.consumeAsync(consumeParams, listener);
    }
}
  • 付出完成后下次付出前查询耗费

public   void  queryPurchasesAsync(Activity context){
    if(billingClient!=null){
        if(!billingClient.isReady()){
            Toast.makeText(context,"BillingClient is not ready",Toast.LENGTH_SHORT).show();
        }
        billingClient.queryPurchasesAsync(
                QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
                new PurchasesResponseListener() {
                    public void onQueryPurchasesResponse(
                            BillingResult billingResult,
                            List<Purchase> purchases) {
                        if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK){
                            if(purchases!=null&&purchases.size()>0){
                                for (Purchase purchase:purchases){
                                    handlePurchase(purchase);
                                }
                            }
                        }
                    }
                }
        );
    }
}

请再 onResume 声明周期办法里边调用

@Override
protected void onResume() {
    super.onResume();
    GooglePay.getInstance().queryPurchasesAsync(EntryEntryAbilityActivity.this);
}

完整Android端代码

EntryEntryAbilityActivity 端代码

package com.example.helloworld;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.android.billingclient.api.BillingClient;
import ohos.stage.ability.adapter.StageActivity;
/**
 * Example ace activity class, which will load ArkUI-X ability instance.
 * StageActivity is provided by ArkUI-X
 * @see <a href=
 * "https://gitee.com/arkui-crossplatform/doc/blob/master/contribute/tutorial/how-to-build-Android-app.md">
 * to build android library</a>
 */
public class EntryEntryAbilityActivity extends StageActivity {
    private static final String TAG = "MainActivity";
    private Context context=EntryEntryAbilityActivity.this;
    private BillingClient billingClient;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e("HiHelloWorld", "EntryEntryAbilityActivity");
        new Bridge(this, "Bridge", getInstanceId());
        //setInstanceName("com.example.helloworld:entry:EntryAbility:");
        setInstanceName("com.example.helloworld:entry:EntryAbility:");
        super.onCreate(savedInstanceState);
        GooglePay.getInstance().initgooglePlay(EntryEntryAbilityActivity.this);
    }
    @Override
    protected void onResume() {
        super.onResume();
        GooglePay.getInstance().queryPurchasesAsync(EntryEntryAbilityActivity.this);
    }
    @Override
    public void onStop() {
        super.onStop();
    }
    @Override
    protected void onPause() {
        super.onPause();
    }
  }

googlepay 工具类代码

package com.example.helloworld;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.ProductDetails;
import com.android.billingclient.api.ProductDetailsResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryProductDetailsParams;
import com.android.billingclient.api.QueryPurchasesParams;
import java.util.ArrayList;
import java.util.List;
/**
 * 作者:xuqing
 * 时间:2024年04月01日 16:20:30
 * 邮箱:1693891473@qq.com
 * 说明:
 */
public  class GooglePay {
    private static final String TAG = "GooglePay";
    private BillingClient billingClient;
    private  static GooglePay instance=null;
    private GooglePay() {
    }
    public static GooglePay getInstance(){
        if(instance==null){
            synchronized (GooglePay.class){
                if(instance==null){
                    instance=new GooglePay();
                }
            }
        }
        return instance;
    }
    private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                    && purchases != null) {
                for (Purchase purchase : purchases) {
                    handlePurchase(purchase);
                    Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                }
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
            } else {
            }
        }
    };
    public void handlePurchase(final Purchase purchase) {
        ConsumeParams consumeParams =
                ConsumeParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .build();
        ConsumeResponseListener listener = new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                    Log.e(TAG, "getSignature: "+ purchase.getSignature() );
                }
            }
        };
        if(billingClient!=null){
            billingClient.consumeAsync(consumeParams, listener);
        }
    }
    public  void initgooglePlay(Activity context) {
        billingClient = BillingClient.newBuilder(context)
                .setListener(purchasesUpdatedListener)
                .enablePendingPurchases()
                .build();
        if(billingClient!=null){
            billingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    if (billingResult.getResponseCode() ==  BillingClient.BillingResponseCode.OK) {
                    }
                }
                @Override
                public void onBillingServiceDisconnected() {
                }
            });
        }
    }
    public   void  toGooglePay(Activity context,String productId){
        //  String productId ="xxxx";
        List<QueryProductDetailsParams.Product> productList= new ArrayList<>();
        productList.add(QueryProductDetailsParams.Product.newBuilder()
                .setProductId(productId)
                .setProductType(BillingClient.ProductType.INAPP)
                .build());
        QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().
                setProductList(productList)
                .build();
        if(billingClient!=null){
            billingClient.queryProductDetailsAsync(
                    queryProductDetailsParams,
                    new ProductDetailsResponseListener() {
                        public void onProductDetailsResponse(BillingResult billingResult,
                                                             List<ProductDetails> productDetailsList) {
                            if(productDetailsList!=null&&productDetailsList.size()>0){
                                ProductDetails productDetails=productDetailsList.get(0);
                                List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList= new ArrayList<>();
                                productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
                                        .setProductDetails(productDetails)
                                        .build());
                                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                                        .setProductDetailsParamsList(productDetailsParamsList)
                                        .build();
                                billingClient.launchBillingFlow((Activity) context, billingFlowParams);
                            }else {
                                Toast.makeText(context,"产品ID无效",Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
            );
        }
    }
    public   void  queryPurchasesAsync(Activity context){
        if(billingClient!=null){
            if(!billingClient.isReady()){
                Toast.makeText(context,"BillingClient is not ready",Toast.LENGTH_SHORT).show();
            }
            billingClient.queryPurchasesAsync(
                    QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
                    new PurchasesResponseListener() {
                        public void onQueryPurchasesResponse(
                                BillingResult billingResult,
                                List<Purchase> purchases) {
                            if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK){
                                if(purchases!=null&&purchases.size()>0){
                                    for (Purchase purchase:purchases){
                                        handlePurchase(purchase);
                                    }
                                }
                            }
                        }
                    }
            );
        }
    }
}

最终总结:

鸿蒙arkui-x才是刚起步期望有更多开发能参加进来一同共同建设完善好生态。也期望国产体系和框架越来越好 最终呢 期望我都文章能协助到各位同学工作和学习 假如你觉得文章还不错麻烦给我三连 关注点赞和转发 谢谢