目录

每张卡券的内容分为两个部分,商户固定信息(模板)及用户特有信息(实例)。

模板:用户共有的字段信息,所有用户将共同享有模板信息字段,如logo、merchantName等。

用户特有信息(实例):用户特有的字段信息,如cardNumber。如果实例和模板中有相同字段则实例信息将覆盖模板信息内容。

用户点击按钮时,打开Webview页面,并通过Intent将JWE发送给华为服务器,获取添加结果并展示给用户。

具体步骤如下:

1 定义模板信息

抽取卡券信息中通用的商户信息作为模板。

  1. HwWalletObject hwWalletObject = new HwWalletObject();
  2. hwWalletObject.setFormatVersion("10.0");
  3. hwWalletObject.setPassStyleIdentifier("Loyalty001"); // 模板标识,唯一值
  4. hwWalletObject.setPassTypeIdentifier("hwpass.loyalty.merchant"); // 注册时的服务号
  5. hwWalletObject.setWebServiceURL("https://www.xxx.com"); // 用户领取卡券时的回调地址
  6. Fields fields = new Fields();
  7. fields.setCountryCode("CN");
  8. // 地理围栏信息
  9. List<Location> locationList = new ArrayList<>();
  10. Location location = new Location();
  11. location.setLongitude("11x.0679603815");
  12. location.setLatitude("2x.6592051284");
  13. locationList.add(location);
  14. fields.setLocationList(locationList);
  15. List<CommonFields> commonFields = new ArrayList<>();
  16. CommonFields cardImage = new CommonFields();
  17. cardImage.setKey("backgroundImage");
  18. cardImage.setValue("https://www.xxx.com/.../cardImage.png"); // 商户会员卡卡面图片URI
  19. commonFields.add(cardImage);
  20. CommonFields logo = new CommonFields();
  21. logo.setKey("logo");
  22. logo.setValue("https://www.xxx.com/.../logo.png"); // 商户LOGO URI
  23. commonFields.add(logo);
  24. // 商户名称,含多语言样例,例如此处设置字符串id为merchantNameI18N,用于在Localized中获取对应语言取值进行展示
  25. CommonFields merchantName = new CommonFields();
  26. merchantName.setKey("merchantName");
  27. merchantName.setValue("Some merchant name");
  28. merchantName.setLocalizedValue("merchantNameI18N");
  29. commonFields.add(merchantName);
  30. // 卡片名称
  31. CommonFields name = new CommonFields();
  32. name.setKey("name");
  33. name.setValue("Loyalty Card");
  34. commonFields.add(name);
  35. fields.setCommonFields(commonFields);
  36. List<AppendFields> appendFields = new ArrayList<>();
  37. AppendFields nearbyLocations = new AppendFields();
  38. nearbyLocations.setKey("nearbyLocations");
  39. nearbyLocations.setValue("https://www.xxx.com/.../nearbyLocation.html"); // 附近门店地址URI
  40. nearbyLocations.setLabel("Nearby Locations");
  41. appendFields.add(nearbyLocations);
  42. AppendFields website = new AppendFields();
  43. website.setKey("website");
  44. website.setValue("https://www.xxx.com/.../merchantMainPage.html"); // 商户主页URI
  45. website.setLabel("Website");
  46. appendFields.add(website);
  47. AppendFields hotline = new AppendFields();
  48. hotline.setKey("hotline");
  49. hotline.setValue("400820XXXX"); // 商户热线
  50. hotline.setLabel("Hotline");
  51. appendFields.add(hotline);
  52. fields.setAppendFields(appendFields);
  53. List<ValueObject> imageList = new ArrayList<>();
  54. ValueObject imagePic = new ValueObject();
  55. imagePic.setValue("https://www.xxx.com/.../banner.png"); // 推广图片
  56. imageList.add(imagePic);
  57. fields.setImageList(imageList);
  58. List<Localized> localizedList = new ArrayList<>();
  59. // 商户中文名称,例如中文语言时,通过上面指定的字符串Id merchantNameI18N匹配到此Value用于展示
  60. Localized merchantNameChinese = new Localized();
  61. merchantNameChinese.setKey("merchantNameI18N");
  62. merchantNameChinese.setLanguage("zh-CN");
  63. merchantNameChinese.setValue("Merchant name in Chinese");
  64. localizedList.add(merchantNameChinese);
  65. // 商户英文名称,例如英文语言时,通过上面指定的字符串Id merchantNameI18N匹配到此Value用于展示
  66. Localized merchantNameEnglish = new Localized();
  67. merchantNameEnglish.setKey("merchantNameI18N");
  68. merchantNameEnglish.setLanguage("en-GB");
  69. merchantNameEnglish.setValue("Merchant name in English");
  70. localizedList.add(merchantNameEnglish);
  71. fields.setLocalized(localizedList);
  72. hwWalletObject.setFields(fields);

通过如下POST接口推送到华为服务器。

  1. POST
  2. https://{walletkit_server_url}/hmspass/v1/loyalty/model

备注:请求地址中的{walletkit_server_url}变量需要开发者根据服务器所属区域自行选择,参考钱包服务器地址列表。

China

passentrust-drcn.wallet.hicloud.com

Russia

passentrust-drru.wallet.hicloud.com

Asia, Africa, and Latin America

passentrust-dra.wallet.hicloud.com

Europe

passentrust-dre.wallet.hicloud.com


推送hwWalletObject代码如下:

  1. boolean validateClass = HwWalletObjectUtil.validateHwWalletObjectClass(hwWalletObject);
  2. if (validateClass) {
  3. // post hwWalletObject to Huawei server
  4. WalletBuildService walletBuildService = new WalletBuildServiceImpl();
  5. HwWalletObject loyaltyClass = walletBuildService.postHwWalletClassToWalletServer("loyalty/model", hwWalletObject);
  6. }

2 在应用中嵌入链接

在应用中自定义按钮,并将如下内容作为链接:

  1. hms://www.huawei.com/payapp/{jwt_content}

3 生成JWE并发送到华为服务器

用户在点击按钮时,生成包含用户特有信息的对象。

  1. HwWalletObject hwWalletObject = new HwWalletObject();
  2. hwWalletObject.setSerialNumber("854687156"); // 对象唯一标识,在模板下唯一
  3. Fields fields = new Fields();
  4. // 状态,生效卡片才能添加
  5. Status status = new Status();
  6. status.setState("active");
  7. status.setEffectTime("2019-11-11T00:00:00.000Z");
  8. status.setExpireTime("2029-11-10T23:59:59.999Z");
  9. fields.setStatus(status);
  10. // 关联优惠券,填入关联优惠券的模板和对象标识
  11. List<LinkedPassId> relatedPassIds = new ArrayList<>();
  12. LinkedPassId linkedCoupon = new LinkedPassId();
  13. linkedCoupon.setTypeId("Coupon template id");
  14. linkedCoupon.setId("Coupon instance id");
  15. relatedPassIds.add(linkedCoupon);
  16. fields.setRelatedPassIds(relatedPassIdss);
  17. // 条形码/二维码
  18. BarCode barCode = new BarCode();
  19. barCode.setText("Refresh every ten minutes");
  20. barCode.setType("codabar"); // codabar or qrCode
  21. barCode.setValue("829383819844342342");
  22. fields.setBarCode(barCode);
  23. List<CommonFields> commonFields = new ArrayList<>();
  24. // 会员名称,含多语言样例
  25. CommonFields accountName = new CommonFields();
  26. accountName.setKey("accountName");
  27. accountName.setValue("Member name");
  28. accountName.setLocalizedValue("accountName18N");
  29. commonFields.add(accountName);
  30. // 卡号
  31. CommonFields cardNumber = new CommonFields();
  32. cardNumber.setKey("cardNumber");
  33. cardNumber.setValue("4527809736");
  34. commonFields.add(cardNumber);
  35. fields.setCommonFields(commonFields);
  36. List<AppendFields> appendFields = new ArrayList<>();
  37. // 会员积分
  38. AppendFields points = new AppendFields();
  39. points.setKey("points");
  40. points.setLabel("Points");
  41. points.setValue("1299");
  42. appendFields.add(points);
  43. AppendFields balance = new AppendFields();
  44. balance.setKey("balance");
  45. balance.setValue("$19");
  46. balance.setLabel("Balance");
  47. appendFields.add(balance);
  48. // 等级
  49. AppendFields level = new AppendFields();
  50. level.setKey("level");
  51. level.setValue("Gloden");
  52. level.setLabel("Level");
  53. appendFields.add(level);
  54. fields.setAppendFields(appendFields);
  55. List<Localized> localizedList = new ArrayList<>();
  56. // 会员中文名称
  57. Localized accountNameChinese = new Localized();
  58. accountNameChinese.setKey("accountName18N");
  59. accountNameChinese.setLanguage("zh-CN");
  60. accountNameChinese.setValue("Member name in Chinese");
  61. localizedList.add(accountNameChinese);
  62. // 会员英文名称
  63. Localized accountNameEnglish = new Localized();
  64. accountNameEnglish.setKey("accountName18N");
  65. accountNameEnglish.setLanguage("en-GB");
  66. accountNameEnglish.setValue("Member name in English");
  67. localizedList.add(accountNameEnglish);
  68. fields.setImageList(localizedList);
  69. hwWalletObject.setFields(fields);

采用JWE格式生成数据,总共分为5段,sessionKey和IV部分建议每次动态变换。。

以下代码中引用但未实现的类(“CommonUtil”,“RandomUtils”,“JweUtil”)均可以在服务器示例代码中查看具体定义。

  1. // 在华为AppGallery Connect网站上注册的应用ID。
  2. String appId = "Replace with your app ID";
  3. //生成一个新的实例并将其绑定到用户,示例代码中使用直接读取json文件的形式来设置Instance,商户接入时建议使用定义HwWalletObject形式来生成JWE数据
  4. //HwWalletObject可以在服务器示例代码中查看具体定义。
  5. //String newInstanceJson = CommonUtil.readWalletObject("LoyaltyInstance.json");
  6. String newInstanceJson = CommonUtil.toJson(hwWalletObject);
  7. JSONObject newInstanceJsonObject = JSONObject.parseObject(newInstanceJson);
  8. newInstanceJsonObject.put("iss", appId);
  9. //生成会话密钥以加密有效载荷数据。 会话密钥是一串随机的十六进制数字。  
  10. String sessionKey = RandomUtils.generateSecureRandomFactor(16);
  11. System.out.println("sessionKey: " + sessionKey);
  12. //华为固定的公开密钥,用于加密会话密钥。
  13. String sessionKeyPublicKey =        "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAgBJB4usbO33Xg5vhJqfHJsMZj44f7rxpjRuPhGy37bUBjSLXN+dS6HpxnZwSVJCtmiydjl3Inq3Mzu4SCGxfb9RIjqRRfHA7ab5p3JnJVQfTEHMHy8XcABl6EPYIJMh26kztPOKU2Mkn6yhRaCurhVUD3n9bD8omiNrR4rg442AJlNamA7vgKs65AoqBuU4NBkGHg0VWWpEHCUx/xyX6hIwqc1aD7P2f62ZHsKpNZBOek/riWhaVx3dTAa9ZS+Av3IGLOZiplhYIow9f8dlWyqs8nff9FZoJO03QhXLvOORT+lPAkW6gFzaoeMaGb40HakkZn3uvlAEKrKrtR0rZEok+N1hnboaAu8oaKK0rF1W6iNrXcFrO0rcrCsFTVF8qCa/1dFmIXwUd2M6cUzT9W0YkNyb6ZBbwEhjwBL4DNW4JfeF2Dzj0eZYlSuYV7e7e1e+XEO8lwPLAiy4bEFAWCaeuDVIhbIoBaU6xHNVQoyzct98gaOYxE4mVDqAUVmhfAgMBAAE=";
  14. //您在AGC上申请服务时生成了一对密钥。在此使用该私钥。
  15. String jweSignPrivateKey = "Replace with your private key.";
  16. //生成JWE
  17. String jweStrByInstanceIds = JweUtil.generateJwe(sessionKey, jweSignPrivateKey,newInstanceJsonObject.toJSONString(), sessionKeyPublicKey);

通过Intent方式将对象JWT发到华为服务器

注:JWE数据需要经过URLEncoder.encode(jweStrByInstanceIds, StandardCharsets.UTF_8.toString())编码。

  1. Intent intent = new Intent(Intent.ACTION_VIEW);
  2. intent.setData(Uri.parse("hms://www.huawei.com/payapp/{" + jwt_content + "}"));
  3. try {
  4. startActivityForResult(intent, requestCode)
  5. } catch (ActivityNotFoundException e) {
  6. …
  7. }