The configuration of the Androidmanifest.xml file is as follows:

<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ConsumptionActivity"></activity> </application> <! - cancel has been check with new huawei HMS - > < the queries > < intent > < action android: name = "com. Huawei. HMS. Core. Aidlservice" / > < / intent > < / queries >Copy the code

Android {compileSdkVersion 30 buildToolsVersion “30.0.2”

DefaultConfig {applicationId "com.qf.myqfpay" minSdkVersion 17 // Cannot be lower than 17 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx. Test. Runner. AndroidJUnitRunner"} signingConfigs {config {storeFile file('D:\\worker\\MyQfpay\\qf.jks') storePassword '123456' keyPassword '123456' keyAlias 'qf' } } buildTypes { debug { signingConfig signingConfigs.config } release { signingConfig signingConfigs.config minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }Copy the code

}

dependencies {

Implementation 'androidx. Appcompat: appcompat: 1.2.0' implementation 'com. Google. Android. Material: material: 1.3.0' Implementation 'androidx. Constraintlayout: constraintlayout: 2.0.4' testImplementation 'junit: junit: 4. +' AndroidTestImplementation 'androidx. Test. Ext: junit: 1.1.2' androidTestImplementation 'androidx. Test. Espresso: espresso - core: 3.3.0' implementation 'com. Huawei. HMS: iap: 5.0.1.300'Copy the code

} apply plugin: ‘com.huawei.agconnect’

The build code below the engineering module is as follows: // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() maven { url ‘developer.huawei.com/repo/’ } } dependencies { classpath “Com. Android. Tools. Build: gradle: 4.4.1.” “

// NOTE: Do not place your application dependencies here; They belong / / in the individual module build. Gradle files classpath 'com. Huawei. Agconnect: agcp: 1.4.1.300'}Copy the code

}

allprojects { repositories { google() jcenter() maven { url ‘developer.huawei.com/repo/’ } } }

task clean(type: Delete) { delete rootProject.buildDir }

There are eight class codes as follows: package com.qf.myqfpay;

import android.text.TextUtils; import android.util.Base64; import android.util.Log;

import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec;

/ * *

  • Signature tool
  • The user’s public key must be placed in
  • And now let’s judge by this

*/ public class CipherUtil { private static final String TAG = “CipherUtil”;

private static final String SIGN_ALGORITHMS = "SHA256WithRSA"; Private static final String PUBLIC_KEY = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAl8YBI1jOQvXUETCCqFEqHmwff7mMpjp5Lo+MajOcsBwa6ZgIu75AAKu7p2qrGy25bXgtpsYkQIt Ald3PEijk7FQ9oDDSrozWdOBKWZXHfUSe6hLH5NTGWdcF/HdZUaviBGe60HazB2y3/UYD1p5TV/DRoN+cUAkAo6VMvTemNB3sDSu52DllDyiT0ozNrI1mNhh mAwI1UXaa/QkrtUUuDHS6k7oRYT0XLNWTZGZXBP8iNG1epciOhpuDDmRPEnIkMuO5+g4KP/RNB1gvl6t1eIEW2hAredvr6qpp/OcwA/SRFJm2MULWG23GhjS DxRMDuvdsISrDfip+gq8Z+ZibUQClipEGfOHgE1TYKPCvAmwVTtWXb0WyGNYp6cuNMHJIuINnZo5fqNCaeKD21ZSe60X0PvLmxx3q0R6AvdLahNthMOZ+DPt MPoSEvZYQquVcbGL9VNZXzgS7vzEgvR/vQ//XwlRPdKuxxIrU0fVDdPwxM8StZjJYeda/dgy4d/PxAgMBAAE="; /** * the method to check the signature for the data returned from the interface * @param content Unsigned data * @param  sign the signature for content * @param publicKey the public of the application * @return boolean */ public static boolean doCheck(String content, String sign, String publicKey) { if (TextUtils.isEmpty(publicKey)) { Log.e(TAG, "publicKey is null"); return false; } if (TextUtils.isEmpty(content) || TextUtils.isEmpty(sign)) { Log.e(TAG, "data is error"); return false; } try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decode(publicKey, Base64.DEFAULT); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS); signature.initVerify(pubKey); signature.update(content.getBytes("utf-8")); boolean bverify = signature.verify(Base64.decode(sign, Base64.DEFAULT)); return bverify; } catch (NoSuchAlgorithmException e) { Log.e(TAG, "doCheck NoSuchAlgorithmException" + e); } catch (InvalidKeySpecException e) { Log.e(TAG, "doCheck InvalidKeySpecException" + e); } catch (InvalidKeyException e) { Log.e(TAG, "doCheck InvalidKeyException" + e); } catch (SignatureException e) { Log.e(TAG, "doCheck SignatureException" + e); } catch (UnsupportedEncodingException e) { Log.e(TAG, "doCheck UnsupportedEncodingException" + e); } return false; } /** * get the publicKey of the application * During the encoding process, avoid storing the public key in clear text. * @return publickey */ public static String getPublicKey(){ return PUBLIC_KEY; }Copy the code

}

/ * *

  • Error code message

/ public class Constants {/* requestCode for pmsPay page */ public static final int REQ_CODE_BUY = 4002;

Public static final int REQ_CODE_LOGIN = 2001; /** requestCode is used to pull out the login page of isEnvReady */ public static final int REQ_CODE_LOGIN = 2001;Copy the code

}

package com.qf.myqfpay;

import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast;

import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity;

import com.huawei.hms.iap.Iap; import com.huawei.hms.iap.IapClient; import com.huawei.hms.iap.entity.InAppPurchaseData; import com.huawei.hms.iap.entity.OrderStatusCode; import com.huawei.hms.iap.entity.OwnedPurchasesResult; import com.huawei.hms.iap.entity.ProductInfo; import com.huawei.hms.iap.entity.ProductInfoResult; import com.huawei.hms.iap.entity.PurchaseIntentResult; import com.huawei.hms.iap.entity.PurchaseResultInfo; import com.huawei.hms.support.api.client.Status;

import org.json.JSONException;

import java.util.ArrayList; import java.util.List;

/ * *

  • consumables

*/ public class ConsumptionActivity extends AppCompatActivity { private static final String PURCHASETOKEN_KEY = “purchasetokenSet”; private static final String GEMS_COUNT_KEY = “gemsCount”; private static final String DATA_NAME = “database”;

private String TAG = "ConsumptionActivity"; private TextView countTextView; / / product display list private ListView consumableProductsListview; Private List<ProductInfo> consumableProducts = new ArrayList<ProductInfo>(); private List<ProductInfo> consumableProducts = new ArrayList<ProductInfo>(); Private ProductListAdapter adapter; Private Button purchaseHisBtn; // Huawei provides the interface class private IapClient mClient. @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_consumption); mClient = Iap.getIapClient(this); initView(); // Check whether there are consumables purchased by the user but not shipped. queryPurchases(null); } private void initView() { findViewById(R.id.progressBar).setVisibility(View.VISIBLE); findViewById(R.id.content).setVisibility(View.GONE); countTextView = (TextView) findViewById(R.id.gems_count); countTextView.setText(String.valueOf(getCountOfGems(this))); consumableProductsListview = (ListView) findViewById(R.id.consumable_product_list1); consumableProductsListview.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<? > parent, View view, int position, long id) { buy(position); }}); purchaseHisBtn = (Button) findViewById(R.id.enter_purchase_his); PurchaseHisBtn. SetOnClickListener (new View. An OnClickListener () {@ Override public void onClick (View View) {/ / historyCopy the code

// Intent intent = new Intent(ConsumptionActivity.this, PurchaseHistoryActivity.class); // startActivity(intent); }}); QueryProducts (); }

/** * query product * productIds */ private void queryProducts() {List<String> productIds = new ArrayList<String>(); productIds.add("123456789"); IapRequestHelper.obtainProductInfo(mClient, productIds, IapClient.PriceType.IN_APP_CONSUMABLE, new IapApiCallback<ProductInfoResult>() { @Override public void onSuccess(ProductInfoResult result) { Log.i(TAG, "obtainProductInfo, success"); if (result == null) { return; } if (result.getProductInfoList() ! = null) { consumableProducts = result.getProductInfoList(); } showProducts(); } @Override public void onFail(Exception e) { Log.e(TAG, "obtainProductInfo: " + e.getMessage()); showProducts(); }}); } private void showProducts() { findViewById(R.id.progressBar).setVisibility(View.GONE); findViewById(R.id.content).setVisibility(View.VISIBLE); adapter = new ProductListAdapter(ConsumptionActivity.this, consumableProducts); consumableProductsListview.setAdapter(adapter); adapter.notifyDataSetChanged(); } /** * Call the obtainOwnedPurchases interface * to get data on consumables that the user has purchased but not shipped. */ private void queryPurchases(String continuationToken) { final String tag = "obtainOwnedPurchases"; IapRequestHelper.obtainOwnedPurchases(mClient, IapClient.PriceType.IN_APP_CONSUMABLE, continuationToken, new IapApiCallback<OwnedPurchasesResult>() { @Override public void onSuccess(OwnedPurchasesResult result) { if (result == null) { Log.e(TAG, tag + " result is null"); return; } Log.i(TAG, "obtainOwnedPurchases, success"); if (result.getInAppPurchaseDataList() ! = null) { List<String> inAppPurchaseDataList = result.getInAppPurchaseDataList(); List<String> inAppSignature= result.getInAppSignature(); for (int i = 0; i < inAppPurchaseDataList.size(); i++) { final String inAppPurchaseData = inAppPurchaseDataList.get(i); final String inAppPurchaseDataSignature = inAppSignature.get(i); deliverProduct(inAppPurchaseData, inAppPurchaseDataSignature); } } if (! TextUtils.isEmpty(result.getContinuationToken())) { queryPurchases(result.getContinuationToken()); } } @Override public void onFail(Exception e) { Log.e(TAG, "obtainOwnedPurchases, type=" + IapClient.PriceType.IN_APP_CONSUMABLE + ", " + e.getMessage()); }}); } / * * * * to delivery @ param inAppPurchaseDataStr * @ param inAppPurchaseDataSignature * / private void deliverProduct (final String inAppPurchaseDataStr, final String inAppPurchaseDataSignature) { if (CipherUtil.doCheck(inAppPurchaseDataStr, inAppPurchaseDataSignature, CipherUtil.getPublicKey())) { try { InAppPurchaseData inAppPurchaseDataBean = new InAppPurchaseData(inAppPurchaseDataStr); if (inAppPurchaseDataBean.getPurchaseState() ! = InAppPurchaseData.PurchaseState.PURCHASED) { return; } String purchaseToken = inAppPurchaseDataBean.getPurchaseToken(); String productId = inAppPurchaseDataBean.getProductId(); if (DeliveryUtils.isDelivered(ConsumptionActivity.this, purchaseToken)) { Toast.makeText(this, productId + " has been delivered", Toast.LENGTH_SHORT).show(); IapRequestHelper.consumeOwnedPurchase(mClient, purchaseToken); } else { if (DeliveryUtils.deliverProduct(this, productId, purchaseToken)) { Log.i(TAG, "delivery success"); Toast.makeText(this, productId + " delivery success", Toast.LENGTH_SHORT).show(); updateNumberOfGems(); // To consume the product after successfully delivering. IapRequestHelper.consumeOwnedPurchase(mClient, purchaseToken); } else { Log.e(TAG, productId + " delivery fail"); Toast.makeText(this, productId + " delivery fail", Toast.LENGTH_SHORT).show(); } } } catch (JSONException e) { Log.e(TAG, "delivery:" + e.getMessage()); } } else { Log.e(TAG, "delivery:" + getString(R.string.verify_signature_fail)); Toast.makeText(this, getString(R.string.verify_signature_fail), Toast.LENGTH_SHORT).show(); }} /** * Update the number of products */ private void updateNumberOfGems() {// Update the number of gems. String countOfGems = String.valueOf(DeliveryUtils.getCountOfGems(ConsumptionActivity.this)); countTextView.setText(countOfGems); } /** * buy @param index */ private void buy(int index) {ProductInfo ProductInfo = consumableproducts.get (index); /** * buy @param index */ private void buy(int index) {ProductInfo ProductInfo = consumableproducts.get (index); IapRequestHelper.createPurchaseIntent(mClient, productInfo.getProductId(), IapClient.PriceType.IN_APP_CONSUMABLE, new IapApiCallback<PurchaseIntentResult>() { @Override public void onSuccess(PurchaseIntentResult result) { if (result == null) { Log.e(TAG, "result is null"); return; } Status status = result.getStatus(); if (status == null) { Log.e(TAG, "status is null"); return; } // You should pull up the page to complete the payment process. IapRequestHelper.startResolutionForResult(ConsumptionActivity.this, status, Constants.REQ_CODE_BUY); } @Override public void onFail(Exception e) {Copy the code

//

}}); } /** * * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i(TAG, "onActivityResult"); super.onActivityResult(requestCode, resultCode, data); If (requestCode == constants.req_code_buy) {if (data == null) {log.e (TAG, "data is null "); return; } PurchaseResultInfo purchaseIntentResult = Iap.getIapClient(this).parsePurchaseResultInfoFromIntent(data); The switch (purchaseIntentResult getReturnCode ()) {case OrderStatusCode. ORDER_STATE_CANCEL: Toast. MakeText (this, "order has been cancelled!" , Toast.LENGTH_SHORT).show(); break; case OrderStatusCode.ORDER_STATE_FAILED: case OrderStatusCode.ORDER_PRODUCT_OWNED: queryPurchases(null); break; Case orderStatusCode.order_state_success: deliverProduct(purchaseIntentResult.getInAppPurchaseData(), purchaseIntentResult.getInAppDataSignature()); break; default: break; } return; * @param context context. * @return long */ public static long getCountOfGems(context context) { SharedPreferences sharedPreferences = context.getSharedPreferences(DATA_NAME, Context.MODE_PRIVATE); long count = sharedPreferences.getLong(GEMS_COUNT_KEY, 0); return count; }Copy the code

}

package com.qf.myqfpay;

import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils;

import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set;

public class DeliveryUtils { private static final String PURCHASETOKEN_KEY = “purchasetokenSet”; private static final String GEMS_COUNT_KEY = “gemsCount”; private static final String DATA_NAME = “database”;

private static Map<String, Integer> getNumOfGems() { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("CProduct01", 5); map.put("CustomizedCProduct01", 10); return map; } /** Determine whether the purchased item has been shipped. @param context Context. Purchasetoken products are generated by huawei Pay server when purchaseToken products are paid and returned to the application via InAppPurchaseData. @return */ public static Boolean isDelivered(Context Context, String purchasetoken) { SharedPreferences sharedPreferences = context.getSharedPreferences(DATA_NAME, Context.MODE_PRIVATE); Set<String> stringSet = sharedPreferences.getStringSet(PURCHASETOKEN_KEY, null); if (stringSet ! = null && stringSet.contains(purchasetoken)) { return true; } return false; } /** * Ship and return the shipping result. * @param context Context. * @param productId Id of the purchased product. *  @param purchaseToken Generated by the Huawei payment server during product payment and returned to the app through InAppPurchaseData. * @return boolean */ public static boolean deliverProduct(Context context, String productId, String purchaseToken) { if (TextUtils.isEmpty(productId) || TextUtils.isEmpty(purchaseToken)) { return false; } if (! getNumOfGems().containsKey(productId)) { return false; } SharedPreferences sharedPreferences = context.getSharedPreferences(DATA_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); long count = sharedPreferences.getLong(GEMS_COUNT_KEY, 0); count += getNumOfGems().get(productId); editor.putLong(GEMS_COUNT_KEY, count); Set<String> stringSet = sharedPreferences.getStringSet(PURCHASETOKEN_KEY, new HashSet<String>()); stringSet.add(purchaseToken); editor.putStringSet(PURCHASETOKEN_KEY, stringSet); return editor.commit(); * @param context context. * @return long */ public static long getCountOfGems(context context) { SharedPreferences sharedPreferences = context.getSharedPreferences(DATA_NAME, Context.MODE_PRIVATE); long count = sharedPreferences.getLong(GEMS_COUNT_KEY, 0); return count; }Copy the code

}

package com.qf.myqfpay;

/ * *

  • Used to call back results from the IAP API.
  • @since 2019/12/9

*/ public interface IapApiCallback {

/** The request succeeded. @param result Result of the successful response. */ void onSuccess(T result); /** Callback failed. @param e Exception from IAPSDK. */ void onFail(Exception e);Copy the code

}

package com.qf.myqfpay;

import android.app.Activity; import android.content.IntentSender; import android.util.Log;

import com.huawei.hmf.tasks.OnFailureListener; import com.huawei.hmf.tasks.OnSuccessListener; import com.huawei.hmf.tasks.Task; import com.huawei.hms.iap.IapApiException; import com.huawei.hms.iap.IapClient; import com.huawei.hms.iap.entity.ConsumeOwnedPurchaseReq; import com.huawei.hms.iap.entity.ConsumeOwnedPurchaseResult; import com.huawei.hms.iap.entity.OwnedPurchasesReq; import com.huawei.hms.iap.entity.OwnedPurchasesResult; import com.huawei.hms.iap.entity.ProductInfoReq; import com.huawei.hms.iap.entity.ProductInfoResult; import com.huawei.hms.iap.entity.PurchaseIntentReq; import com.huawei.hms.iap.entity.PurchaseIntentResult; import com.huawei.hms.support.api.client.Status;

import java.util.List;

public class IapRequestHelper { private final static String TAG = “IapRequestHelper”;

/**
 * 获取在 AppGallery Connect 中配置的应用内产品详细信息。
 *
 * @param iapClient  IapClient 实例调用获取产品信息 API。
 * @param productIds 要查询的产品 ID 列表。每个产品 ID
 *                   必须存在并且在当前应用中是唯一的。
 * @param type       应用内产品类型。该值包含:
 *                   0:消耗品 1:不可消耗品 2 自动更新订阅
 * @param callback   IapApiCallback
 */
public static void obtainProductInfo(IapClient iapClient, final List<String> productIds, int type, final IapApiCallback callback) {
    Log.i(TAG, "call obtainProductInfo");

    Task<ProductInfoResult> task = iapClient.obtainProductInfo(createProductInfoReq(type, productIds));
    task.addOnSuccessListener(new OnSuccessListener<ProductInfoResult>() {
        @Override
        public void onSuccess(ProductInfoResult result) {
            Log.i(TAG, "obtainProductInfo, success");
            callback.onSuccess(result);
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            Log.e(TAG, "obtainProductInfo, fail");
            callback.onFail(e);
        }
    });
}

/**
 * 创建一个 ProductInfoReq 对象。
 *
 * @param type 应用内产品类型。该值包含: 0:消耗品 1:非消耗品 2
 *             自动续订订阅 @param productIds
 *             要查询的产品 ID 列表。每个产品
 *             ID 必须存在并且在当前应用中是唯一的。
 * @return 产品信息请求
 */
private static ProductInfoReq createProductInfoReq(int type, List<String> productIds) {
    ProductInfoReq req = new ProductInfoReq();
    req.setPriceType(type);
    req.setProductIds(productIds);
    return req;
}

/**
 * 查询所有已订阅的应用内商品信息,包括消耗品、非消耗品和自动续期订阅。
 * 如果返回消耗品,则系统需要进行交付并调用consumeOwnedPurchase API 来消费产品。
 * 如果退回非消耗品,则无需消耗应用内商品。如果返回订阅,
 * 则返回该用户在该应用下的所有现有订阅关系。
 *
 * @param mClient  IapClient 实例调用获取OwnedPurchases API。
 * @param type     应用内产品类型。该值包含:
 *                 0:消耗品
 *                 1:不可消耗品
 *                 2 自动更新订阅
 * @param callback IapApiCallback
 */
public static void obtainOwnedPurchases(IapClient mClient, final int type, String continuationToken, final IapApiCallback callback) {
    Log.i(TAG, "call obtainOwnedPurchases");
    Task<OwnedPurchasesResult> task = mClient.obtainOwnedPurchases(IapRequestHelper.createOwnedPurchasesReq(type, continuationToken));
    task.addOnSuccessListener(new OnSuccessListener<OwnedPurchasesResult>() {
        @Override
        public void onSuccess(OwnedPurchasesResult result) {
            Log.i(TAG, "obtainOwnedPurchases, success");
            callback.onSuccess(result);

        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            Log.e(TAG, "obtainOwnedPurchases, fail");
            callback.onFail(e);
        }
    });

}

/**
 * 创建一个OwnedPurchasesReq 对象。 @param type type 应用内商品类型。该值包含:
 * 0:消耗品 1:不可消耗品 2 自动更新订阅 @param continuationToken
 * 从获取OwnedPurchases api 或获取OwnedPurchaseRecord api 返回的数据位置标志。
 * @return OwnedPurchasesReq
 */
private static OwnedPurchasesReq createOwnedPurchasesReq(int type, String continuationToken) {
    OwnedPurchasesReq req = new OwnedPurchasesReq();
    req.setPriceType(type);
    req.setContinuationToken(continuationToken);
    return req;
}
/**
 使用 priceType 0 消费所有未消费的购买。
 @param iapClient IapClient 实例调用消耗 OwnedPurchase API。
 @param purchaseToken 在产品支付过程中由华为支付服务器生成,
 通过InAppPurchaseData返回给应用。
 */
public static void consumeOwnedPurchase(IapClient iapClient, String purchaseToken) {
    Log.i(TAG, "call consumeOwnedPurchase");
    Task<ConsumeOwnedPurchaseResult> task = iapClient.consumeOwnedPurchase(createConsumeOwnedPurchaseReq(purchaseToken));
    task.addOnSuccessListener(new OnSuccessListener<ConsumeOwnedPurchaseResult>() {
        @Override
        public void onSuccess(ConsumeOwnedPurchaseResult result) {
            // Consume success.
            Log.i(TAG, "consumeOwnedPurchase success");
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            if (e instanceof IapApiException) {
                IapApiException apiException = (IapApiException)e;
                int returnCode = apiException.getStatusCode();
                Log.e(TAG, "consumeOwnedPurchase fail, IapApiException returnCode: " + returnCode);
            } else {
                // Other external errors
                Log.e(TAG, e.getMessage());
            }

        }
    });

}
/**
 创建一个 ConsumeOwnedPurchaseReq 对象。
 @param purchaseToken 在产品支付过程中由华为支付服务器生成,
 通过InAppPurchaseData返回给应用。应用程序将此参数传递给华为支付服务器更新订单状态,
 然后交付应用程序内产品。 @return ConsumeOwnedPurchaseReq
 */
private static ConsumeOwnedPurchaseReq createConsumeOwnedPurchaseReq(String purchaseToken) {
    ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
    req.setPurchaseToken(purchaseToken);
    req.setDeveloperChallenge("testConsume");
    return req;
}
/**
 在 PMS @param iapClient IapClient 实例中为应用内产品创建订单以调用
 createPurchaseIntent API。要支付的应用内商品的
 @param productId ID。应用内产品 ID 是您在
 AppGallery Connect 中的应用内产品配置过程中设置的产品 ID。
 @param type 应用内产品类型。该值包含:
 0:消耗品 1:不可消耗品 2 自动更新订阅 @param callback IapApiCallback
 */
public static void createPurchaseIntent(final IapClient iapClient, String productId, int type, final IapApiCallback callback) {
    Log.i(TAG, "call createPurchaseIntent");
    Task<PurchaseIntentResult> task = iapClient.createPurchaseIntent(createPurchaseIntentReq(type, productId));
    task.addOnSuccessListener(new OnSuccessListener<PurchaseIntentResult>() {
        @Override
        public void onSuccess(PurchaseIntentResult result) {
            Log.i(TAG, "createPurchaseIntent, success");
            callback.onSuccess(result);
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            Log.e(TAG, "createPurchaseIntent, fail");
            callback.onFail(e);

        }
    });
}
/**
 * 创建一个 PurchaseIntentReq 对象。 @param type 应用内产品类型。该值包含:
 * 0:消耗品
 * 1:非消耗品
 * 2 自动更新订阅 @param productId 要支付的应用内商品的 ID。
 * 应用内产品 ID 是您在 AppGallery Connect
 * 中的应用内产品配置过程中设置的产品 ID。
 * @return PurchaseIntentReq
 */
private static PurchaseIntentReq createPurchaseIntentReq(int type, String productId) {
    PurchaseIntentReq req = new PurchaseIntentReq();
    req.setPriceType(type);
    req.setProductId(productId);
    req.setDeveloperPayload("testPurchase");
    return req;
}
/**
 开始一项活动。
 @param activity 启动新页面的活动。
 @param status 该参数包含支付页面的pendingIntent 对象。
 @param reqCode 结果代码.
 */
public static void startResolutionForResult(Activity activity, Status status, int reqCode) {
    if (status == null) {
        Log.e(TAG, "status is null");
        return;
    }
    if (status.hasResolution()) {
        try {
            status.startResolutionForResult(activity, reqCode);
        } catch (IntentSender.SendIntentException exp) {
            Log.e(TAG, exp.getMessage());
        }
    } else {
        Log.e(TAG, "intent is null");
    }
}
Copy the code

}

package com.qf.myqfpay;

import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView;

import com.huawei.hms.iap.IapClient; import com.huawei.hms.iap.entity.ProductInfo;

import java.util.List;

/ * *

  • List adapter

*/ public class ProductListAdapter extends BaseAdapter { private Context mContext; private List productInfos;

public ProductListAdapter(Context context, List<ProductInfo> productInfos) { mContext = context; this.productInfos = productInfos; } @Override public int getCount() { return productInfos.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ProductInfo productInfo = productInfos.get(position); ProductListViewHolder holder = null; if (null == convertView) { convertView = LayoutInflater.from(mContext).inflate(R.layout.item_layout, null); holder = new ProductListViewHolder(convertView); convertView.setTag(holder); } else { holder = (ProductListViewHolder) convertView.getTag(); } holder.productName.setText(productInfo.getProductName()); holder.productPrice.setText(productInfo.getPrice()); if (productInfo.getPriceType() == IapClient.PriceType.IN_APP_NONCONSUMABLE) { holder.imageView.setVisibility(View.GONE);  } return convertView; } @Override public long getItemId(int position) { return position; } @Override public Object getItem(int position) { if (productInfos ! = null && productInfos.size() > 0) { return productInfos.get(position); } return null; } static class ProductListViewHolder { TextView productName; TextView productPrice; ImageView imageView; ProductListViewHolder(View view) { productName = (TextView) view.findViewById(R.id.item_name); productPrice = (TextView) view.findViewById(R.id.item_price); imageView = (ImageView) view.findViewById(R.id.item_image); }}Copy the code

}

package com.qf.myqfpay;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView xiaoPay, feiPay;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { xiaoPay = findViewById(R.id.tv); feiPay = findViewById(R.id.tv_fei); xiaoPay.setOnClickListener(this); feiPay.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv: startActivity(new Intent(this,ConsumptionActivity.class)); break; case R.id.tv_fei: break; default: break; }}Copy the code

}