├── Open Source Software Notice.doc ├── src ├── test │ ├── resources │ │ ├── data │ │ │ ├── PartialUpdateOfferInstance.json │ │ │ ├── Messages.json │ │ │ ├── PartialUpdateEventTicketInstance.json │ │ │ ├── PartialUpdateGiftCardInstance.json │ │ │ ├── PartialUpdateLoyaltyInstance.json │ │ │ ├── PartialUpdateFlightInstance.json │ │ │ ├── PartialUpdateTransitInstance.json │ │ │ ├── PartialUpdateFlightModel.json │ │ │ ├── PartialUpdateGiftCardModel.json │ │ │ ├── PartialUpdateLoyaltyModel.json │ │ │ ├── PartialUpdateOfferModel.json │ │ │ ├── PartialUpdateTransitModel.json │ │ │ ├── PartialUpdateEventTicketModel.json │ │ │ ├── PartialUpdateStdCarKeyInstance.json │ │ │ ├── PartialUpdateStdCarKeyModel.json │ │ │ ├── LinkedOfferInstanceIds.json │ │ │ ├── OfferInstance.json │ │ │ ├── FullUpdateOfferInstance.json │ │ │ ├── StdCarKeyModel.json │ │ │ ├── FullUpdateStdCarKeyModel.json │ │ │ ├── FullUpdateFlightInstance.json │ │ │ ├── TransitInstance.json │ │ │ ├── FullUpdateTransitInstance.json │ │ │ ├── GiftCardInstance.json │ │ │ ├── FullUpdateGiftCardInstance.json │ │ │ ├── FlightInstance.json │ │ │ ├── LoyaltyInstance.json │ │ │ ├── FullUpdateLoyaltyInstance.json │ │ │ ├── EventTicketInstance.json │ │ │ ├── FullUpdateEventTicketInstance.json │ │ │ ├── StdCarKeyInstance.json │ │ │ ├── FullUpdateStdCarkeyInstance.json │ │ │ ├── EventTicketModel.json │ │ │ ├── FullUpdateEventTicketModel.json │ │ │ ├── TransitModel.json │ │ │ ├── FullUpdateTransitModel.json │ │ │ ├── LoyaltyModel.json │ │ │ ├── OfferModel.json │ │ │ ├── FullUpdateOfferModel.json │ │ │ ├── FullUpdateLoyaltyModel.json │ │ │ ├── GiftCardModel.json │ │ │ ├── FullUpdateGiftCardModel.json │ │ │ ├── FlightModel.json │ │ │ └── FullUpdateFlightModel.json │ │ └── release.config.properties │ └── java │ │ └── com │ │ └── huawei │ │ └── wallet │ │ └── hms │ │ ├── stdcarkey │ │ ├── StdCarKeyQuerySupportFeatureTest.java │ │ ├── StdCarKeyModelTest.java │ │ └── StdCarKeyInstanceTest.java │ │ ├── signature │ │ └── SignatureTest.java │ │ ├── jwe │ │ └── JweTest.java │ │ ├── offer │ │ ├── OfferModelTest.java │ │ └── OfferInstanceTest.java │ │ ├── flight │ │ ├── FlightModelTest.java │ │ └── FlightInstanceTest.java │ │ ├── loyalty │ │ └── LoyaltyModelTest.java │ │ ├── transit │ │ ├── TransitModelTest.java │ │ └── TransitInstanceTest.java │ │ ├── giftcard │ │ ├── GiftCardModelTest.java │ │ └── GiftCardInstanceTest.java │ │ └── eventticket │ │ ├── EventTicketModelTest.java │ │ └── EventTicketInstanceTest.java └── main │ └── java │ └── com │ └── huawei │ └── wallet │ ├── nsp │ └── NetworkService.java │ ├── util │ ├── AesUtil.java │ ├── RsaUtil.java │ ├── ConfigUtil.java │ ├── HwWalletObjectUtil.java │ └── JweUtil.java │ └── hms │ └── ServerApiService.java ├── pom.xml ├── serverdemo.iml ├── README_ZH.md └── LICENSE /Open Source Software Notice.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HMS-Core/hms-wallet-severdemo/HEAD/Open Source Software Notice.doc -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateOfferInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "status": { 4 | "state": "inactive" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/resources/data/Messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "messageList": [ 3 | { 4 | "key": "message[10]", 5 | "value": "Hello everyone!", 6 | "label": "Message" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateEventTicketInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "appendFields": [ 4 | { 5 | "key": "gate", 6 | "value": "10" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateGiftCardInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "balance", 6 | "value": "$50" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateLoyaltyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "appendFields": [ 4 | { 5 | "key": "points", 6 | "value": "1500" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateFlightInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "boardingSequence", 6 | "value": "3" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateTransitInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "ticketStatus", 6 | "value": "Used" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateFlightModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateGiftCardModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateLoyaltyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateOfferModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateTransitModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateEventTicketModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "key": "logo", 6 | "value": "https:/www.huawei.com/new_image_url.png" 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateStdCarKeyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "linkDevicePass": { 3 | "webServiceURL": "https://xxx", 4 | "nfcType": "1", 5 | "serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 6 | "passVersion": "10.0", 7 | "spPublickey": "xxxx", 8 | "token": "12345679" 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/data/PartialUpdateStdCarKeyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "commonFields": [ 4 | { 5 | "value": "xxx", 6 | "key": "logo" 7 | }, 8 | { 9 | "value": "xxx", 10 | "key": "backgroundImage" 11 | }, 12 | { 13 | "value": "xxx", 14 | "key": "picUrl" 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/data/LinkedOfferInstanceIds.json: -------------------------------------------------------------------------------- 1 | { 2 | "addOffers": [ 3 | { 4 | "passTypeIdentifier": "Replace with the passTypeIdentifier of the instance you want to add", 5 | "instanceId": "Replace with the serialNumber of the instance you want to add" 6 | } 7 | ], 8 | "deleteOffers": [ 9 | { 10 | "passTypeIdentifier": "Replace with the passTypeIdentifier of the instance you want to delete", 11 | "instanceId": "Replace with the serialNumber of the instance you want to delete" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /src/test/resources/data/OfferInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489234", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "OfferTestModel", 5 | "serialNumber": "OfferPass50001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "562348969211212", 14 | "type": "codabar", 15 | "value": "562348969211212", 16 | "encoding": "UTF-8" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateOfferInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489234", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "OfferTestModel", 5 | "serialNumber": "OfferPass50001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "562348969211212", 14 | "type": "codabar", 15 | "value": "562348969211212", 16 | "encoding": "UTF-8" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/resources/data/StdCarKeyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "10.0", 3 | "passTypeIdentifier": "hwpass.stdcarkey.bluecarkey.xxx", 4 | "passStyleIdentifier": "xxxxxxx", 5 | "organizationName": "xxx车钥匙", 6 | "fields": { 7 | "appendFields": [ 8 | { 9 | "label": "NFCCardFlag", 10 | "value": "true", 11 | "key": "isCreateWhiteCard" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "label": "卡面主标题", 17 | "value": "我的爱车", 18 | "key": "merchantName" 19 | }, 20 | { 21 | "label": "卡面副标题", 22 | "value": "xxx车钥匙", 23 | "key": "name" 24 | }, 25 | { 26 | "value": "xxxx", 27 | "key": "logo" 28 | }, 29 | { 30 | "value": "xxxx", 31 | "key": "backgroundImage" 32 | }, 33 | { 34 | "value": "xxxx", 35 | "key": "picUrl" 36 | } 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateStdCarKeyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "10.0", 3 | "passTypeIdentifier": "hwpass.stdcarkey.bluecarkey.xxx", 4 | "passStyleIdentifier": "xxxxxxx", 5 | "organizationName": "xxx车钥匙", 6 | "fields": { 7 | "appendFields": [ 8 | { 9 | "label": "NFCCardFlag", 10 | "value": "true", 11 | "key": "isCreateWhiteCard" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "label": "卡面主标题", 17 | "value": "第一辆车", 18 | "key": "merchantName" 19 | }, 20 | { 21 | "label": "卡面副标题", 22 | "value": "第一辆车钥匙", 23 | "key": "name" 24 | }, 25 | { 26 | "value": "https://xxx/xxx.png", 27 | "key": "logo" 28 | }, 29 | { 30 | "value": "https://xxx/xxx.webp", 31 | "key": "backgroundImage" 32 | }, 33 | { 34 | "value": "https://xxx/xxx.png", 35 | "key": "picUrl" 36 | } 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateFlightInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489692", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "FlightTestModel", 5 | "serialNumber": "FlightPass20001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "seatNumber", 15 | "value": "15B" 16 | }, 17 | { 18 | "key": "passengerName", 19 | "value": "Joe Wiley" 20 | }, 21 | { 22 | "key": "boardingSequence", 23 | "value": "2" 24 | }, 25 | { 26 | "key": "flightClass", 27 | "value": "Business Class" 28 | } 29 | ], 30 | "barCode": { 31 | "text": "5623489692", 32 | "type": "qrCode", 33 | "value": "5623489692", 34 | "encoding": "UTF-8" 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/test/resources/data/TransitInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489611", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "TransitTestModel", 5 | "serialNumber": "TransitPass60001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "ticketStatus", 15 | "value": "Not Used" 16 | } 17 | ], 18 | "barCode": { 19 | "text": "562348969211212", 20 | "type": "codabar", 21 | "value": "562348969211212", 22 | "encoding": "UTF-8" 23 | }, 24 | "ticketInfoList": [ 25 | { 26 | "key": "carriage", 27 | "value": "8" 28 | }, 29 | { 30 | "key": "seatNumber", 31 | "value": "7A" 32 | }, 33 | { 34 | "key": "seatCoach", 35 | "value": "14" 36 | } 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateTransitInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489611", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "TransitTestModel", 5 | "serialNumber": "TransitPass60001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "ticketStatus", 15 | "value": "Not Used" 16 | } 17 | ], 18 | "barCode": { 19 | "text": "562348969211212", 20 | "type": "codabar", 21 | "value": "562348969211212", 22 | "encoding": "UTF-8" 23 | }, 24 | "ticketInfoList": [ 25 | { 26 | "key": "carriage", 27 | "value": "7" 28 | }, 29 | { 30 | "key": "seatNumber", 31 | "value": "9C" 32 | }, 33 | { 34 | "key": "seatCoach", 35 | "value": "2" 36 | } 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/resources/data/GiftCardInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 3 | "passStyleIdentifier": "GiftCardTestModel", 4 | "organizationPassId": "356688115", 5 | "serialNumber": "GiftCardPass30001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "1118466050", 14 | "type": "codabar", 15 | "value": "1118466050", 16 | "encoding": "UTF-8" 17 | }, 18 | "commonFields": [ 19 | { 20 | "key": "cardNumber", 21 | "value": "356688115", 22 | "label": "Card Number" 23 | }, 24 | { 25 | "key": "balance", 26 | "value": "$199", 27 | "label": "Balance" 28 | }, 29 | { 30 | "key": "balanceRefreshTime", 31 | "value": "Thursday, Dec 12,2018" 32 | }, 33 | { 34 | "key": "pin", 35 | "value": "118.91", 36 | "label": "PIN Number" 37 | } 38 | ] 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateGiftCardInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 3 | "passStyleIdentifier": "GiftCardTestModel", 4 | "organizationPassId": "356688115", 5 | "serialNumber": "GiftCardPass30001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "1118466050", 14 | "type": "codabar", 15 | "value": "1118466050", 16 | "encoding": "UTF-8" 17 | }, 18 | "commonFields": [ 19 | { 20 | "key": "cardNumber", 21 | "value": "12345678", 22 | "label": "Card Number" 23 | }, 24 | { 25 | "key": "balance", 26 | "value": "$888", 27 | "label": "Balance" 28 | }, 29 | { 30 | "key": "balanceRefreshTime", 31 | "value": "Thursday, Dec 12,2018" 32 | }, 33 | { 34 | "key": "pin", 35 | "value": "118.91", 36 | "label": "PIN Number" 37 | } 38 | ] 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/resources/data/FlightInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489692", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "FlightTestModel", 5 | "serialNumber": "FlightPass20001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "seatNumber", 15 | "value": "12A" 16 | }, 17 | { 18 | "key": "passengerName", 19 | "value": "Wang Xiao" 20 | }, 21 | { 22 | "key": "boardingSequence", 23 | "value": "1" 24 | }, 25 | { 26 | "key": "flightClass", 27 | "value": "First Class" 28 | } 29 | ], 30 | "appendFields": [ 31 | { 32 | "key": "confirmationNumber", 33 | "value": "ITK919" 34 | } 35 | ], 36 | "barCode": { 37 | "text": "5623489692", 38 | "type": "qrCode", 39 | "value": "5623489692", 40 | "encoding": "UTF-8" 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/test/resources/data/LoyaltyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 3 | "passStyleIdentifier": "LoyaltyTestModel", 4 | "organizationPassId": "356688115", 5 | "serialNumber": "LoyaltyPass40001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "1118466050", 14 | "type": "codabar", 15 | "value": "1118466050", 16 | "encoding": "UTF-8" 17 | }, 18 | "commonFields": [ 19 | { 20 | "key": "cardNumber", 21 | "value": "356688115", 22 | "label": "Card Number" 23 | }, 24 | { 25 | "key": "balance", 26 | "value": "$199", 27 | "label": "Balance" 28 | }, 29 | { 30 | "key": "balanceRefreshTime", 31 | "value": "Thursday, Dec 12,2018" 32 | }, 33 | { 34 | "key": "memberName", 35 | "value": "Joe Wiley", 36 | "label": "Card Holder" 37 | } 38 | ], 39 | "appendFields": [ 40 | { 41 | "key": "points", 42 | "value": "2000", 43 | "label": "Points" 44 | } 45 | ] 46 | } 47 | } -------------------------------------------------------------------------------- /src/test/resources/release.config.properties: -------------------------------------------------------------------------------- 1 | gw.appid={Replace with your App ID} 2 | gw.appid.secret={Replace with your App Secret} 3 | gw.tokenUrl=https://oauth-login.cloud.huawei.com/oauth2/v3/token 4 | 5 | # Replace {walletkit_server_url} with one of the following strings according to your account location. 6 | # wallet-passentrust-drcn.cloud.huawei.com.cn for Chinese mainland 7 | # wallet-passentrust-dra.cloud.huawei.asia for Asia 8 | # wallet-passentrust-dre.cloud.huawei.eu for Europe 9 | # wallet-passentrust-dra.cloud.huawei.lat for Latin America 10 | # wallet-passentrust-drru.cloud.huawei.ru for Russia 11 | walletServerBaseUrl=https://{walletkit_server_url}/hmspass 12 | 13 | # You generated a pair of RSA keys while applying for services on AGC. Use that private key here. 14 | servicePrivateKey={Replace with your private key} 15 | 16 | # Replace {walletkit_website_url} with one of the following strings according to your account location. 17 | # walletpass-drcn.cloud.huawei.com for Chinese mainland 18 | # walletpass-dra.cloud.huawei.com for Asia 19 | # walletpass-dre.cloud.huawei.com for Europe 20 | # walletpass-dra.cloud.huawei.com for Latin America 21 | # walletpass-drru.cloud.huawei.com for Russia 22 | walletWebsiteBaseUrl=https://{walletkit_website_url}/walletkit/consumer/pass/save -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateLoyaltyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 3 | "passStyleIdentifier": "LoyaltyTestModel", 4 | "organizationPassId": "356688115", 5 | "serialNumber": "LoyaltyPass40001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "barCode": { 13 | "text": "1118466050", 14 | "type": "codabar", 15 | "value": "1118466050", 16 | "encoding": "UTF-8" 17 | }, 18 | "commonFields": [ 19 | { 20 | "key": "cardNumber", 21 | "value": "12345678", 22 | "label": "Card Number" 23 | }, 24 | { 25 | "key": "balance", 26 | "value": "$666", 27 | "label": "Balance" 28 | }, 29 | { 30 | "key": "balanceRefreshTime", 31 | "value": "Thursday, Dec 12,2018" 32 | }, 33 | { 34 | "key": "memberName", 35 | "value": "Joe Wiley", 36 | "label": "Card Holder" 37 | } 38 | ], 39 | "appendFields": [ 40 | { 41 | "key": "points", 42 | "value": "8000", 43 | "label": "Points" 44 | } 45 | ] 46 | } 47 | } -------------------------------------------------------------------------------- /src/test/resources/data/EventTicketInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489234", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "EventTicketTestModel", 5 | "serialNumber": "EventTicketPass10001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "ticketNumber", 15 | "value": "12345678" 16 | } 17 | ], 18 | "appendFields": [ 19 | { 20 | "key": "gate", 21 | "value": "1", 22 | "label": "Gate" 23 | }, 24 | { 25 | "key": "section", 26 | "value": "2", 27 | "label": "Section" 28 | }, 29 | { 30 | "key": "row", 31 | "value": "10", 32 | "label": "Row" 33 | }, 34 | { 35 | "key": "seat", 36 | "value": "20", 37 | "label": "Seat" 38 | }, 39 | { 40 | "key": "userName", 41 | "value": "Joe Wiley" 42 | } 43 | ], 44 | "barCode": { 45 | "text": "562348969211212", 46 | "type": "codabar", 47 | "value": "562348969211212", 48 | "encoding": "UTF-8" 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateEventTicketInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationPassId": "5623489234", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "EventTicketTestModel", 5 | "serialNumber": "EventTicketPass10001", 6 | "fields": { 7 | "status": { 8 | "state": "active", 9 | "effectTime": "2020-04-06T00:00:00.111Z", 10 | "expireTime": "2030-04-06T00:00:00.111Z" 11 | }, 12 | "commonFields": [ 13 | { 14 | "key": "ticketNumber", 15 | "value": "12345678" 16 | } 17 | ], 18 | "appendFields": [ 19 | { 20 | "key": "gate", 21 | "value": "2", 22 | "label": "Gate" 23 | }, 24 | { 25 | "key": "section", 26 | "value": "3", 27 | "label": "Section" 28 | }, 29 | { 30 | "key": "row", 31 | "value": "20", 32 | "label": "Row" 33 | }, 34 | { 35 | "key": "seat", 36 | "value": "10", 37 | "label": "Seat" 38 | }, 39 | { 40 | "key": "userName", 41 | "value": "Joe Wiley" 42 | } 43 | ], 44 | "barCode": { 45 | "text": "562348969211212", 46 | "type": "codabar", 47 | "value": "562348969211212", 48 | "encoding": "UTF-8" 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/test/resources/data/StdCarKeyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationName": "xxx车钥匙", 3 | "passTypeIdentifier": "hwpass.stdcarkey.bluecarkey.xxx", 4 | "passStyleIdentifier": "xxxxxxx", 5 | "organizationPassId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 6 | "serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 7 | "fields": { 8 | "timeList": [ 9 | { 10 | "value": "timeListValue", 11 | "key": "linkDevicePassExpireTime" 12 | } 13 | ], 14 | "status": { 15 | "state": "active", 16 | "effectTime": "2020-04-06T00:00:00Z", 17 | "expireTime": "2030-04-06T00:00:00Z" 18 | }, 19 | "commonFields": [ 20 | { 21 | "value": "xxx.CarActivity", 22 | "key": "bleTargetActivity" 23 | }, 24 | { 25 | "value": "hwpass.carkey.ble", 26 | "key": "bleFeature" 27 | }, 28 | { 29 | "value": "01:23:45:67:89:AB", 30 | "key": "bleMacAddress" 31 | }, 32 | { 33 | "label": "readerId", 34 | "value": "xxxxxxxxxxxxxxxxxxxxx", 35 | "key": "readerMatchValue" 36 | }, 37 | { 38 | "label": "主卡服务号", 39 | "value": "hwpass.stdcarkey.std", 40 | "key": "ownerPassTypeIdentifier" 41 | }, 42 | { 43 | "value": "0000xxxx-0000-1000-8000-00805f9b34fb", 44 | "key": "bleServiceUuid" 45 | }, 46 | { 47 | "value": "xxx", 48 | "key": "bleTargetPackage" 49 | }, 50 | { 51 | "value": "xxx", 52 | "key": "bleTargetService" 53 | } 54 | ] 55 | }, 56 | "linkDevicePass": { 57 | "webServiceURL": "https://xxxxx", 58 | "nfcType": "1", 59 | "serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 60 | "passVersion": "10.0", 61 | "spPublickey": "xxxxxxx", 62 | "token": "xxxxxx" 63 | } 64 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateStdCarkeyInstance.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationName": "xxx车钥匙", 3 | "passTypeIdentifier": "hwpass.stdcarkey.bluecarkey.xxx", 4 | "passStyleIdentifier": "xxxxxxx", 5 | "organizationPassId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 6 | "serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 7 | "fields": { 8 | "timeList": [ 9 | { 10 | "value": "timeListValue", 11 | "key": "linkDevicePassExpireTime" 12 | } 13 | ], 14 | "status": { 15 | "state": "active", 16 | "effectTime": "2020-04-06T00:00:00Z", 17 | "expireTime": "2040-04-06T00:00:00Z" 18 | }, 19 | "commonFields": [ 20 | { 21 | "value": "xxx.CarActivity", 22 | "key": "bleTargetActivity" 23 | }, 24 | { 25 | "value": "hwpass.carkey.ble", 26 | "key": "bleFeature" 27 | }, 28 | { 29 | "value": "01:23:45:67:89:AB", 30 | "key": "bleMacAddress" 31 | }, 32 | { 33 | "label": "readerId", 34 | "value": "xxxxxxxxxxxxxxxxxxxxx", 35 | "key": "readerMatchValue" 36 | }, 37 | { 38 | "label": "主卡服务号", 39 | "value": "hwpass.stdcarkey.std", 40 | "key": "ownerPassTypeIdentifier" 41 | }, 42 | { 43 | "value": "0000xxxx-0000-1000-8000-00805f9b34fb", 44 | "key": "bleServiceUuid" 45 | }, 46 | { 47 | "value": "xxx", 48 | "key": "bleTargetPackage" 49 | }, 50 | { 51 | "value": "xxx", 52 | "key": "bleTargetService" 53 | } 54 | ] 55 | }, 56 | "linkDevicePass": { 57 | "webServiceURL": "https://xxxxx", 58 | "nfcType": "1", 59 | "serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 60 | "passVersion": "10.0", 61 | "spPublickey": "xxxxxxx", 62 | "token": "xxxxxx" 63 | } 64 | } -------------------------------------------------------------------------------- /src/test/resources/data/EventTicketModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "EventTicketTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "name", 21 | "value": "XXX Party Ticket" 22 | }, 23 | { 24 | "key": "merchantName", 25 | "value": "Huawei", 26 | "localizedValue": "merchantNameI18N" 27 | }, 28 | { 29 | "key": "address", 30 | "value": "XXX location" 31 | }, 32 | { 33 | "key": "ticketType", 34 | "value": "Adult ticket" 35 | } 36 | ], 37 | "appendFields": [ 38 | { 39 | "key": "backgroundColor", 40 | "value": "#FF1C2635" 41 | } 42 | ], 43 | "imageList": [ 44 | { 45 | "key": "mainImage[0]", 46 | "value": "https:/www.huawei.com/XXX0.png" 47 | }, 48 | { 49 | "key": "mainImage[1]", 50 | "value": "https:/www.huawei.com/XXX1.png" 51 | }, 52 | { 53 | "key": "mainImage[2]", 54 | "value": "https:/www.huawei.com/XXX2.png" 55 | } 56 | ], 57 | "messageList": [ 58 | { 59 | "key": "message[0]", 60 | "value": "Welcome to the party!", 61 | "label": "Message" 62 | } 63 | ], 64 | "timeList": [ 65 | { 66 | "key": "startTime", 67 | "value": "2020-01-22T09:20:00.083Z" 68 | }, 69 | { 70 | "key": "endTime", 71 | "value": "2020-01-22T12:20:00.083Z" 72 | } 73 | ], 74 | "localized": [ 75 | { 76 | "key": "merchantNameI18N", 77 | "language": "zh-cn", 78 | "value": "华为" 79 | }, 80 | { 81 | "key": "merchantNameI18N", 82 | "language": "en", 83 | "value": "Huawei" 84 | } 85 | ] 86 | } 87 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateEventTicketModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "EventTicketTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "name", 21 | "value": "XXX Party Ticket" 22 | }, 23 | { 24 | "key": "merchantName", 25 | "value": "Huawei", 26 | "localizedValue": "merchantNameI18N" 27 | }, 28 | { 29 | "key": "address", 30 | "value": "YYY location" 31 | }, 32 | { 33 | "key": "ticketType", 34 | "value": "Adult ticket" 35 | } 36 | ], 37 | "appendFields": [ 38 | { 39 | "key": "backgroundColor", 40 | "value": "#FF1C2635" 41 | } 42 | ], 43 | "imageList": [ 44 | { 45 | "key": "mainImage[0]", 46 | "value": "https:/www.huawei.com/XXX0.png" 47 | }, 48 | { 49 | "key": "mainImage[1]", 50 | "value": "https:/www.huawei.com/XXX1.png" 51 | }, 52 | { 53 | "key": "mainImage[2]", 54 | "value": "https:/www.huawei.com/XXX2.png" 55 | } 56 | ], 57 | "messageList": [ 58 | { 59 | "key": "message[0]", 60 | "value": "Welcome to the party!", 61 | "label": "Message" 62 | } 63 | ], 64 | "timeList": [ 65 | { 66 | "key": "startTime", 67 | "value": "2020-01-22T18:00:00.083Z" 68 | }, 69 | { 70 | "key": "endTime", 71 | "value": "2020-01-22T22:00:00.083Z" 72 | } 73 | ], 74 | "localized": [ 75 | { 76 | "key": "merchantNameI18N", 77 | "language": "zh-cn", 78 | "value": "华为" 79 | }, 80 | { 81 | "key": "merchantNameI18N", 82 | "language": "en", 83 | "value": "Huawei" 84 | } 85 | ] 86 | } 87 | } -------------------------------------------------------------------------------- /src/test/resources/data/TransitModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "TransitTestModel", 5 | "organizationName": "XXX Railway", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "merchantName", 21 | "value": "XXX Railway", 22 | "localizedValue": "merchantNameI18N" 23 | } 24 | ], 25 | "appendFields": [ 26 | { 27 | "key": "backgroundColor", 28 | "value": "#FF37C09A" 29 | }, 30 | { 31 | "key": "ticketFaceValue", 32 | "value": "$127" 33 | } 34 | ], 35 | "imageList": [ 36 | { 37 | "key": "mainImage[0]", 38 | "value": "https:/www.huawei.com/XXX0.png" 39 | }, 40 | { 41 | "key": "mainImage[1]", 42 | "value": "https:/www.huawei.com/XXX1.png" 43 | }, 44 | { 45 | "key": "mainImage[2]", 46 | "value": "https:/www.huawei.com/XXX2.png" 47 | } 48 | ], 49 | "messageList": [ 50 | { 51 | "key": "message[0]", 52 | "value": "Have a nice trip!", 53 | "label": "Message" 54 | } 55 | ], 56 | "ticketInfoList": [ 57 | { 58 | "key": "departureStationName", 59 | "value": "Euston" 60 | }, 61 | { 62 | "key": "arrivalStationName", 63 | "value": "Lime Street" 64 | }, 65 | { 66 | "key": "departureCityName", 67 | "value": "London" 68 | }, 69 | { 70 | "key": "arrivalCityName", 71 | "value": "Liverpool" 72 | }, 73 | { 74 | "key": "departureTime", 75 | "value": "2019-12-09T10:49:00.010Z" 76 | }, 77 | { 78 | "key": "arrivalTime", 79 | "value": "2019-12-09T13:55:00.010Z" 80 | }, 81 | { 82 | "key": "platform", 83 | "value": "2" 84 | } 85 | ], 86 | "localized": [ 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "zh-cn", 90 | "value": "XXX铁路公司" 91 | }, 92 | { 93 | "key": "merchantNameI18N", 94 | "language": "en", 95 | "value": "XXX Railway" 96 | } 97 | ] 98 | } 99 | } -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/stdcarkey/StdCarKeyQuerySupportFeatureTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.stdcarkey; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | import com.huawei.wallet.hms.ServerApiService; 21 | import com.huawei.wallet.hms.ServerApiServiceImpl; 22 | import org.junit.Test; 23 | 24 | /** 25 | * Queries the function list supported by Huawei pay according to the specified mobile phone's terminal, rom and client version. 26 | * 27 | * @since 2021-05-27 28 | */ 29 | public class StdCarKeyQuerySupportFeatureTest { 30 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 31 | 32 | /** 33 | * Add a digital car key instance to HMS wallet server. 34 | * Run the "createDigitalCarKeyInstance" test before running this test. 35 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 36 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 37 | * POST http://XXX/hmspass/v2/key_stdcar/instance 38 | */ 39 | @Test 40 | public void querySupportedFeatured() { 41 | System.out.println("querySupportedFeatured begin."); 42 | // Post the new digital car key instance to HMS wallet server. 43 | String terminal = "Replace with your real mobile's terminal number"; 44 | String romVersion = "Replace with your real mobile's rom version"; 45 | String clientVersion = "Replace with your real mobile's client version"; 46 | String urlSegment = "/v1/" + terminal + "/" + romVersion + "/" + clientVersion; 47 | 48 | JSONObject response = serverApiService.queryIssuerAndFlag(urlSegment); 49 | System.out.println("Queried supported featured: " + JSONObject.toJSONString(response)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateTransitModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "TransitTestModel", 5 | "organizationName": "XXX Railway", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "merchantName", 21 | "value": "XXX Railway", 22 | "localizedValue": "merchantNameI18N" 23 | } 24 | ], 25 | "appendFields": [ 26 | { 27 | "key": "backgroundColor", 28 | "value": "#FF37C09A" 29 | }, 30 | { 31 | "key": "ticketFaceValue", 32 | "value": "$100" 33 | } 34 | ], 35 | "imageList": [ 36 | { 37 | "key": "mainImage[0]", 38 | "value": "https:/www.huawei.com/XXX0.png" 39 | }, 40 | { 41 | "key": "mainImage[1]", 42 | "value": "https:/www.huawei.com/XXX1.png" 43 | }, 44 | { 45 | "key": "mainImage[2]", 46 | "value": "https:/www.huawei.com/XXX2.png" 47 | } 48 | ], 49 | "messageList": [ 50 | { 51 | "key": "message[0]", 52 | "value": "Have a nice trip!", 53 | "label": "Message" 54 | } 55 | ], 56 | "ticketInfoList": [ 57 | { 58 | "key": "departureStationName", 59 | "value": "Euston" 60 | }, 61 | { 62 | "key": "arrivalStationName", 63 | "value": "Lime Street" 64 | }, 65 | { 66 | "key": "departureCityName", 67 | "value": "London" 68 | }, 69 | { 70 | "key": "arrivalCityName", 71 | "value": "Liverpool" 72 | }, 73 | { 74 | "key": "departureTime", 75 | "value": "2019-12-09T16:00:00.010Z" 76 | }, 77 | { 78 | "key": "arrivalTime", 79 | "value": "2019-12-09T19:00:00.010Z" 80 | }, 81 | { 82 | "key": "platform", 83 | "value": "3" 84 | } 85 | ], 86 | "localized": [ 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "zh-cn", 90 | "value": "XXX铁路公司" 91 | }, 92 | { 93 | "key": "merchantNameI18N", 94 | "language": "en", 95 | "value": "XXX Railway" 96 | } 97 | ] 98 | } 99 | } -------------------------------------------------------------------------------- /src/test/resources/data/LoyaltyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "LoyaltyTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "backgroundImage", 21 | "value": "https:/www.huawei.com/XXX.png" 22 | }, 23 | { 24 | "key": "name", 25 | "value": "XXX Gold Loyalty Card", 26 | "localizedValue": "cardName" 27 | }, 28 | { 29 | "key": "merchantName", 30 | "value": "XXX Super Market", 31 | "localizedValue": "merchantNameI18N" 32 | } 33 | ], 34 | "appendFields": [ 35 | { 36 | "key": "backgroundColor", 37 | "value": "#483d8b" 38 | }, 39 | { 40 | "key": "hotline", 41 | "value": "8006011450", 42 | "label": "Tel" 43 | }, 44 | { 45 | "key": "website", 46 | "value": "https://www.huawei.com", 47 | "label": "Website" 48 | }, 49 | { 50 | "key": "level", 51 | "value": "Gold", 52 | "label": "Membership Tier" 53 | } 54 | ], 55 | "messageList": [ 56 | { 57 | "key": "message[0]", 58 | "value": "Best wishes.", 59 | "label": "Message" 60 | } 61 | ], 62 | "imageList": [ 63 | { 64 | "key": "mainImage[0]", 65 | "value": "https:/www.huawei.com/XXX0.png" 66 | }, 67 | { 68 | "key": "mainImage[1]", 69 | "value": "https:/www.huawei.com/XXX1.png" 70 | }, 71 | { 72 | "key": "mainImage[2]", 73 | "value": "https:/www.huawei.com/XXX2.png" 74 | } 75 | ], 76 | "localized": [ 77 | { 78 | "key": "cardName", 79 | "language": "zh-cn", 80 | "value": "XXX 黄金会员卡" 81 | }, 82 | { 83 | "key": "cardName", 84 | "language": "en", 85 | "value": "XXX Gold Loyalty Card" 86 | }, 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "zh-cn", 90 | "value": "XXX 超市" 91 | }, 92 | { 93 | "key": "merchantNameI18N", 94 | "language": "en", 95 | "value": "XXX Super Market" 96 | } 97 | ] 98 | } 99 | } -------------------------------------------------------------------------------- /src/test/resources/data/OfferModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "OfferTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "name", 21 | "value": "50%-Off Coupon", 22 | "localizedValue": "nameI18N" 23 | }, 24 | { 25 | "key": "providerName", 26 | "value": "XXX Company" 27 | }, 28 | { 29 | "key": "merchantName", 30 | "value": "HUAWEI Vmall", 31 | "localizedValue": "merchantNameI18N" 32 | } 33 | ], 34 | "appendFields": [ 35 | { 36 | "key": "details", 37 | "value": "Detail information of this coupon.", 38 | "localizedValue": "detailsI18N" 39 | }, 40 | { 41 | "key": "declaration", 42 | "value": "Coupon disclaimer provided by merchant.", 43 | "localizedValue": "declarationI18N" 44 | }, 45 | { 46 | "key": "backgroundColor", 47 | "value": "#FF1C2635" 48 | } 49 | ], 50 | "messageList": [ 51 | { 52 | "key": "message[0]", 53 | "value": "Don't miss this great offer!", 54 | "label": "Important!", 55 | "localizedValue": "message[0]I18N" 56 | } 57 | ], 58 | "imageList": [ 59 | { 60 | "key": "mainImage[0]", 61 | "value": "https:/www.huawei.com/XXX0.png" 62 | }, 63 | { 64 | "key": "mainImage[1]", 65 | "value": "https:/www.huawei.com/XXX1.png" 66 | }, 67 | { 68 | "key": "mainImage[2]", 69 | "value": "https:/www.huawei.com/XXX2.png" 70 | } 71 | ], 72 | "localized": [ 73 | { 74 | "key": "merchantNameI18N", 75 | "language": "zh-cn", 76 | "value": "华为商城" 77 | }, 78 | { 79 | "key": "merchantNameI18N", 80 | "language": "en", 81 | "value": "HUAWEI Vmall" 82 | }, 83 | { 84 | "key": "message[0]I18N", 85 | "language": "zh-cn", 86 | "value": "不要错过这次的优惠!" 87 | }, 88 | { 89 | "key": "message[0]I18N", 90 | "language": "en", 91 | "value": "Don't miss this great offer!" 92 | } 93 | ] 94 | } 95 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateOfferModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "OfferTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "name", 21 | "value": "70%-Off Coupon", 22 | "localizedValue": "nameI18N" 23 | }, 24 | { 25 | "key": "providerName", 26 | "value": "YYY Producer" 27 | }, 28 | { 29 | "key": "merchantName", 30 | "value": "HUAWEI Vmall", 31 | "localizedValue": "merchantNameI18N" 32 | } 33 | ], 34 | "appendFields": [ 35 | { 36 | "key": "details", 37 | "value": "Detail information of this coupon.", 38 | "localizedValue": "detailsI18N" 39 | }, 40 | { 41 | "key": "declaration", 42 | "value": "Coupon disclaimer provided by merchant.", 43 | "localizedValue": "declarationI18N" 44 | }, 45 | { 46 | "key": "backgroundColor", 47 | "value": "#FF1C2635" 48 | } 49 | ], 50 | "messageList": [ 51 | { 52 | "key": "message[0]", 53 | "value": "Don't miss this great offer!", 54 | "label": "Important!", 55 | "localizedValue": "message[0]I18N" 56 | } 57 | ], 58 | "imageList": [ 59 | { 60 | "key": "mainImage[0]", 61 | "value": "https:/www.huawei.com/XXX0.png" 62 | }, 63 | { 64 | "key": "mainImage[1]", 65 | "value": "https:/www.huawei.com/XXX1.png" 66 | }, 67 | { 68 | "key": "mainImage[2]", 69 | "value": "https:/www.huawei.com/XXX2.png" 70 | } 71 | ], 72 | "localized": [ 73 | { 74 | "key": "merchantNameI18N", 75 | "language": "zh-cn", 76 | "value": "华为商城" 77 | }, 78 | { 79 | "key": "merchantNameI18N", 80 | "language": "en", 81 | "value": "HUAWEI Vmall" 82 | }, 83 | { 84 | "key": "message[0]I18N", 85 | "language": "zh-cn", 86 | "value": "不要错过这次的优惠!" 87 | }, 88 | { 89 | "key": "message[0]I18N", 90 | "language": "en", 91 | "value": "Don't miss this great offer!" 92 | } 93 | ] 94 | } 95 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateLoyaltyModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "LoyaltyTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "backgroundImage", 21 | "value": "https:/www.huawei.com/XXX.png" 22 | }, 23 | { 24 | "key": "name", 25 | "value": "XXX Diamond Loyalty Card", 26 | "localizedValue": "cardName" 27 | }, 28 | { 29 | "key": "merchantName", 30 | "value": "XXX Super Market", 31 | "localizedValue": "merchantNameI18N" 32 | } 33 | ], 34 | "appendFields": [ 35 | { 36 | "key": "backgroundColor", 37 | "value": "#483d8b" 38 | }, 39 | { 40 | "key": "hotline", 41 | "value": "8006011450", 42 | "label": "Tel" 43 | }, 44 | { 45 | "key": "website", 46 | "value": "https://www.huawei.com", 47 | "label": "Website" 48 | }, 49 | { 50 | "key": "level", 51 | "value": "Diamond", 52 | "label": "Membership Tier" 53 | } 54 | ], 55 | "messageList": [ 56 | { 57 | "key": "message[0]", 58 | "value": "Best wishes.", 59 | "label": "Message" 60 | } 61 | ], 62 | "imageList": [ 63 | { 64 | "key": "mainImage[0]", 65 | "value": "https:/www.huawei.com/XXX0.png" 66 | }, 67 | { 68 | "key": "mainImage[1]", 69 | "value": "https:/www.huawei.com/XXX1.png" 70 | }, 71 | { 72 | "key": "mainImage[2]", 73 | "value": "https:/www.huawei.com/XXX2.png" 74 | } 75 | ], 76 | "localized": [ 77 | { 78 | "key": "cardName", 79 | "language": "zh-cn", 80 | "value": "XXX 钻石会员卡" 81 | }, 82 | { 83 | "key": "cardName", 84 | "language": "en", 85 | "value": "XXX Diamond Loyalty Card" 86 | }, 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "zh-cn", 90 | "value": "XXX 超市" 91 | }, 92 | { 93 | "key": "merchantNameI18N", 94 | "language": "en", 95 | "value": "XXX Super Market" 96 | } 97 | ] 98 | } 99 | } -------------------------------------------------------------------------------- /src/test/resources/data/GiftCardModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "GiftCardTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "backgroundImage", 21 | "value": "https:/www.huawei.com/XXX.png" 22 | }, 23 | { 24 | "key": "name", 25 | "value": "Gift Card" 26 | }, 27 | { 28 | "key": "merchantName", 29 | "value": "XXX Super Market", 30 | "localizedValue": "merchantNameI18N" 31 | }, 32 | { 33 | "key": "eventNumber", 34 | "value": "223421515222143", 35 | "label": "Event Number", 36 | "localizedValue": "eventNameI18n" 37 | } 38 | ], 39 | "appendFields": [ 40 | { 41 | "key": "backgroundColor", 42 | "value": "#483d8b" 43 | }, 44 | { 45 | "key": "hotline", 46 | "value": "8006011450", 47 | "label": "Tel" 48 | }, 49 | { 50 | "key": "website", 51 | "value": "https://www.huawei.com", 52 | "label": "Website" 53 | } 54 | ], 55 | "messageList": [ 56 | { 57 | "key": "message[0]", 58 | "value": "Welcome to use this gift card.", 59 | "label": "Welcome" 60 | }, 61 | { 62 | "key": "message[1]", 63 | "value": "This gift card is used for XXX.", 64 | "label": "Explanation" 65 | } 66 | ], 67 | "imageList": [ 68 | { 69 | "key": "mainImage[0]", 70 | "value": "https:/www.huawei.com/XXX0.png" 71 | }, 72 | { 73 | "key": "mainImage[1]", 74 | "value": "https:/www.huawei.com/XXX1.png" 75 | }, 76 | { 77 | "key": "mainImage[2]", 78 | "value": "https:/www.huawei.com/XXX2.png" 79 | } 80 | ], 81 | "localized": [ 82 | { 83 | "key": "merchantNameI18N", 84 | "language": "zh-cn", 85 | "value": "某某超市" 86 | }, 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "en", 90 | "value": "XXX Super Market" 91 | }, 92 | { 93 | "key": "eventNumberI18N", 94 | "language": "zh-cn", 95 | "value": "活动编号" 96 | }, 97 | { 98 | "key": "eventNumberI18N", 99 | "language": "en", 100 | "value": "Event Number" 101 | } 102 | ] 103 | } 104 | } -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/nsp/NetworkService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.nsp; 18 | 19 | import com.huawei.wallet.util.ConfigUtil; 20 | 21 | import com.alibaba.fastjson.JSONObject; 22 | 23 | import org.apache.logging.log4j.util.Strings; 24 | import org.springframework.http.HttpEntity; 25 | import org.springframework.http.HttpHeaders; 26 | import org.springframework.http.HttpMethod; 27 | import org.springframework.http.MediaType; 28 | import org.springframework.http.ResponseEntity; 29 | import org.springframework.util.LinkedMultiValueMap; 30 | import org.springframework.util.MultiValueMap; 31 | import org.springframework.web.client.RestTemplate; 32 | 33 | /** 34 | * Implementation of invoking gateway service. 35 | * 36 | * @since 2019-07-26 37 | */ 38 | public class NetworkService { 39 | private static final RestTemplate REST_TEMPLATE = new RestTemplate(); 40 | 41 | public static String getToken(String clientId, String clientSecret) { 42 | HttpHeaders header = new HttpHeaders(); 43 | header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 44 | 45 | MultiValueMap map = new LinkedMultiValueMap<>(); 46 | map.add("grant_type", "client_credentials"); 47 | map.add("client_id", clientId); 48 | map.add("client_secret", clientSecret); 49 | 50 | String tokenUrl = ConfigUtil.instants().getValue("gw.tokenUrl"); 51 | 52 | // Send the http request and get response. 53 | HttpEntity> entity = new HttpEntity<>(map, header); 54 | ResponseEntity exchange = 55 | REST_TEMPLATE.exchange(tokenUrl, HttpMethod.POST, entity, JSONObject.class); 56 | 57 | JSONObject response = exchange.getBody(); 58 | 59 | // Return the token. 60 | if (response == null) { 61 | throw new NullPointerException("Get null token response."); 62 | } 63 | String accessToken = response.getString("access_token"); 64 | if (Strings.isEmpty(accessToken)) { 65 | throw new NullPointerException("Get null access token."); 66 | } 67 | return accessToken; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateGiftCardModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "GiftCardTestModel", 5 | "organizationName": "Huawei", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "backgroundImage", 21 | "value": "https:/www.huawei.com/XXX.png" 22 | }, 23 | { 24 | "key": "name", 25 | "value": "Christmas Gift Card" 26 | }, 27 | { 28 | "key": "merchantName", 29 | "value": "XXX Super Market", 30 | "localizedValue": "merchantNameI18N" 31 | }, 32 | { 33 | "key": "eventNumber", 34 | "value": "223421510894697", 35 | "label": "Event Number", 36 | "localizedValue": "eventNameI18n" 37 | } 38 | ], 39 | "appendFields": [ 40 | { 41 | "key": "backgroundColor", 42 | "value": "#483d8b" 43 | }, 44 | { 45 | "key": "hotline", 46 | "value": "8006011450", 47 | "label": "Tel" 48 | }, 49 | { 50 | "key": "website", 51 | "value": "https://www.huawei.com", 52 | "label": "Website" 53 | } 54 | ], 55 | "messageList": [ 56 | { 57 | "key": "message[0]", 58 | "value": "Welcome to use this gift card.", 59 | "label": "Welcome" 60 | }, 61 | { 62 | "key": "message[1]", 63 | "value": "This gift card can only be used on Christmas Eve.", 64 | "label": "Explanation" 65 | } 66 | ], 67 | "imageList": [ 68 | { 69 | "key": "mainImage[0]", 70 | "value": "https:/www.huawei.com/XXX0.png" 71 | }, 72 | { 73 | "key": "mainImage[1]", 74 | "value": "https:/www.huawei.com/XXX1.png" 75 | }, 76 | { 77 | "key": "mainImage[2]", 78 | "value": "https:/www.huawei.com/XXX2.png" 79 | } 80 | ], 81 | "localized": [ 82 | { 83 | "key": "merchantNameI18N", 84 | "language": "zh-cn", 85 | "value": "某某超市" 86 | }, 87 | { 88 | "key": "merchantNameI18N", 89 | "language": "en", 90 | "value": "XXX Super Market" 91 | }, 92 | { 93 | "key": "eventNumberI18N", 94 | "language": "zh-cn", 95 | "value": "活动编号" 96 | }, 97 | { 98 | "key": "eventNumberI18N", 99 | "language": "en", 100 | "value": "Event Number" 101 | } 102 | ] 103 | } 104 | } -------------------------------------------------------------------------------- /src/test/resources/data/FlightModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "1.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "FlightTestModel", 5 | "organizationName": "XXX Airline", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "merchantName", 21 | "value": "XXX Airline", 22 | "localizedValue": "merchantNameI18N" 23 | }, 24 | { 25 | "key": "flightNumber", 26 | "value": "MU2887" 27 | }, 28 | { 29 | "key": "departureTerminal", 30 | "value": "T2" 31 | }, 32 | { 33 | "key": "boardingGate", 34 | "value": "45" 35 | }, 36 | { 37 | "key": "departureCity", 38 | "value": "Nanjing" 39 | }, 40 | { 41 | "key": "arrivalTerminal", 42 | "value": "T3" 43 | }, 44 | { 45 | "key": "arrivalCity", 46 | "value": "Shenzhen" 47 | } 48 | ], 49 | "appendFields": [ 50 | { 51 | "key": "backgroundColor", 52 | "value": "#FF1C2635" 53 | } 54 | ], 55 | "imageList": [ 56 | { 57 | "key": "mainImage[0]", 58 | "value": "https:/www.huawei.com/XXX0.png" 59 | }, 60 | { 61 | "key": "mainImage[1]", 62 | "value": "https:/www.huawei.com/XXX1.png" 63 | }, 64 | { 65 | "key": "mainImage[2]", 66 | "value": "https:/www.huawei.com/XXX2.png" 67 | } 68 | ], 69 | "messageList": [ 70 | { 71 | "key": "message[0]", 72 | "value": "Enjoy the journey!", 73 | "label": "Message" 74 | } 75 | ], 76 | "timeList": [ 77 | { 78 | "key": "departureTime", 79 | "value": "2020-05-09T10:30:00.010Z" 80 | }, 81 | { 82 | "key": "scheduledDepartureTime", 83 | "value": "2020-05-09T10:30:00.010Z" 84 | }, 85 | { 86 | "key": "boardingTime", 87 | "value": "2020-05-09T10:00:00.010Z" 88 | }, 89 | { 90 | "key": "arrivalTime", 91 | "value": "2020-05-09T12:30:00.010Z" 92 | }, 93 | { 94 | "key": "scheduledArrivalTime", 95 | "value": "2020-05-09T12:30:00.010Z" 96 | } 97 | ], 98 | "localized": [ 99 | { 100 | "key": "merchantNameI18N", 101 | "language": "zh-cn", 102 | "value": "XXX 航空公司" 103 | }, 104 | { 105 | "key": "merchantNameI18N", 106 | "language": "en", 107 | "value": "XXX Airline" 108 | } 109 | ] 110 | } 111 | } -------------------------------------------------------------------------------- /src/test/resources/data/FullUpdateFlightModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "passVersion": "2.0", 3 | "passTypeIdentifier": "Replace with the Service ID you applied on AGC", 4 | "passStyleIdentifier": "FlightTestModel", 5 | "organizationName": "XXX Airline", 6 | "fields": { 7 | "countryCode": "zh", 8 | "locationList": [ 9 | { 10 | "longitude": "114.0679603815", 11 | "latitude": "22.6592051284" 12 | } 13 | ], 14 | "commonFields": [ 15 | { 16 | "key": "logo", 17 | "value": "https:/www.huawei.com/XXX.png" 18 | }, 19 | { 20 | "key": "merchantName", 21 | "value": "XXX Airline", 22 | "localizedValue": "merchantNameI18N" 23 | }, 24 | { 25 | "key": "flightNumber", 26 | "value": "MU2887" 27 | }, 28 | { 29 | "key": "departureTerminal", 30 | "value": "T3" 31 | }, 32 | { 33 | "key": "boardingGate", 34 | "value": "108" 35 | }, 36 | { 37 | "key": "departureCity", 38 | "value": "Nanjing" 39 | }, 40 | { 41 | "key": "arrivalTerminal", 42 | "value": "T3" 43 | }, 44 | { 45 | "key": "arrivalCity", 46 | "value": "Shenzhen" 47 | } 48 | ], 49 | "appendFields": [ 50 | { 51 | "key": "backgroundColor", 52 | "value": "#FF1C2635" 53 | } 54 | ], 55 | "imageList": [ 56 | { 57 | "key": "mainImage[0]", 58 | "value": "https:/www.huawei.com/XXX0.png" 59 | }, 60 | { 61 | "key": "mainImage[1]", 62 | "value": "https:/www.huawei.com/XXX1.png" 63 | }, 64 | { 65 | "key": "mainImage[2]", 66 | "value": "https:/www.huawei.com/XXX2.png" 67 | } 68 | ], 69 | "messageList": [ 70 | { 71 | "key": "message[0]", 72 | "value": "Enjoy the journey!", 73 | "label": "Message" 74 | } 75 | ], 76 | "timeList": [ 77 | { 78 | "key": "departureTime", 79 | "value": "2020-05-09T12:30:00.010Z" 80 | }, 81 | { 82 | "key": "scheduledDepartureTime", 83 | "value": "2020-05-09T10:30:00.010Z" 84 | }, 85 | { 86 | "key": "boardingTime", 87 | "value": "2020-05-09T12:00:00.010Z" 88 | }, 89 | { 90 | "key": "arrivalTime", 91 | "value": "2020-05-09T14:30:00.010Z" 92 | }, 93 | { 94 | "key": "scheduledArrivalTime", 95 | "value": "2020-05-09T12:30:00.010Z" 96 | } 97 | ], 98 | "localized": [ 99 | { 100 | "key": "merchantNameI18N", 101 | "language": "zh-cn", 102 | "value": "XXX 航空公司" 103 | }, 104 | { 105 | "key": "merchantNameI18N", 106 | "language": "en", 107 | "value": "XXX Airline" 108 | } 109 | ] 110 | } 111 | } -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/util/AesUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.util; 18 | 19 | import java.nio.charset.StandardCharsets; 20 | import java.security.NoSuchAlgorithmException; 21 | import java.security.SecureRandom; 22 | import java.security.spec.AlgorithmParameterSpec; 23 | import javax.crypto.Cipher; 24 | import javax.crypto.SecretKey; 25 | import javax.crypto.spec.GCMParameterSpec; 26 | import javax.crypto.spec.SecretKeySpec; 27 | import org.apache.commons.codec.Charsets; 28 | import org.apache.commons.codec.binary.Hex; 29 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 30 | 31 | /** 32 | * AES-encryption utility class. 33 | * 34 | * @since 2019-12-12 35 | */ 36 | public class AesUtil { 37 | private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider(); 38 | 39 | public AesUtil() { 40 | } 41 | 42 | /** 43 | * AES-GCM encryption. 44 | * 45 | * @param plainData the data to be encrypted. 46 | * @param secretKeyStr encryption secret key. 47 | * @param iv encryption random iv. 48 | * @return the encrypted string. 49 | */ 50 | public static String encryptByGcm(String plainData, String secretKeyStr, byte[] iv) { 51 | try { 52 | byte[] secretKeyByte = secretKeyStr.getBytes(StandardCharsets.UTF_8); 53 | byte[] plainByte = plainData.getBytes(Charsets.UTF_8); 54 | SecretKey secretKey = new SecretKeySpec(secretKeyByte, "AES"); 55 | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", BOUNCY_CASTLE_PROVIDER); 56 | AlgorithmParameterSpec spec = new GCMParameterSpec(128, iv); 57 | cipher.init(1, secretKey, spec); 58 | byte[] fBytes = cipher.doFinal(plainByte); 59 | return new String(Hex.encodeHex(fBytes, false)); 60 | } catch (Exception e) { 61 | throw new IllegalArgumentException("GCM encryption failed. Error: " + e.getMessage()); 62 | } 63 | } 64 | 65 | /** 66 | * Generate encryption random iv. 67 | * 68 | * @param size iv length 69 | * @return encryption the byte array. 70 | */ 71 | public static byte[] getIvByte(int size) { 72 | try { 73 | SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 74 | byte[] bytes = new byte[size]; 75 | sr.nextBytes(bytes); 76 | return bytes; 77 | } catch (NoSuchAlgorithmException e) { 78 | throw new UnsupportedOperationException("Get iv bytes failed. Error: " + e.getMessage()); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.huawei.wisecloud.wallet 8 | serverdemo 9 | 1.0.0-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | 21 | com.fasterxml.jackson.core 22 | jackson-databind 23 | 2.10.0 24 | 25 | 26 | jackson-annotations 27 | com.fasterxml.jackson.core 28 | 29 | 30 | jackson-core 31 | com.fasterxml.jackson.core 32 | 33 | 34 | 35 | 36 | 37 | 38 | junit 39 | junit 40 | 4.13.1 41 | test 42 | 43 | 44 | 45 | 46 | org.bouncycastle 47 | bcpkix-jdk15on 48 | 1.64 49 | 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-web 55 | 2.2.1.RELEASE 56 | 57 | 58 | jackson-databind 59 | com.fasterxml.jackson.core 60 | 61 | 62 | 63 | 64 | 65 | com.alibaba 66 | fastjson 67 | 1.2.62 68 | 69 | 70 | 71 | org.apache.httpcomponents 72 | httpclient 73 | 4.5.7 74 | 75 | 76 | 77 | javax.activation 78 | activation 79 | 1.1.1 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/hms/ServerApiService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms; 18 | 19 | import com.alibaba.fastjson.JSONArray; 20 | import com.alibaba.fastjson.JSONObject; 21 | 22 | /** 23 | * Interface of invoking HMS wallet server APIs. 24 | * 25 | * @since 2019-11-05 26 | */ 27 | public interface ServerApiService { 28 | /** 29 | * Post a HwWalletObject to wallet server. 30 | * 31 | * @param urlSegment request URL segment. 32 | * @param body JSON-type HwWalletObject. 33 | * @return the posted HwWalletObject. 34 | */ 35 | JSONObject postToWalletServer(String urlSegment, String body); 36 | 37 | /** 38 | * query Huawei Wallet supported features from wallet server. 39 | * 40 | * @param urlSegment request URL segment. 41 | * @return the supported flag. 42 | */ 43 | JSONObject queryIssuerAndFlag(String urlSegment); 44 | 45 | /** 46 | * Return the model/instance for a given model/instance ID. 47 | * 48 | * @param urlSegment request URL segment. 49 | * @param id model ID or instance ID. 50 | * @return the model/instance. 51 | */ 52 | JSONObject getHwWalletObjectById(String urlSegment, String id); 53 | 54 | /** 55 | * Return a list of models belonging to a specific appId. 56 | * 57 | * @param urlSegment request URL segment. 58 | * @param pageSize maximum number of model in the returned list. All model created by the issuer 59 | * will be returned if pageSize is null. 60 | * @return models 61 | */ 62 | JSONArray getModels(String urlSegment, Integer pageSize); 63 | 64 | /** 65 | * Return a list of some instance belonging to a specific model. 66 | * 67 | * @param urlSegment request URL segment. 68 | * @param modelId model ID. 69 | * @param pageSize max number of instance in the returned list. All instance belongs to the wallet 70 | * model will be returned if pageSize is null. 71 | * @return instances 72 | */ 73 | JSONArray getInstances(String urlSegment, String modelId, Integer pageSize); 74 | 75 | /** 76 | * Overwrite a model/instance. 77 | * 78 | * @param urlSegment request URL segment. 79 | * @param id model/instance ID. 80 | * @param body JSON-type HwWalletObject. 81 | * @return the updated model/instance. 82 | */ 83 | JSONObject fullUpdateHwWalletObject(String urlSegment, String id, String body); 84 | 85 | /** 86 | * Update a model/instance. 87 | * 88 | * @param urlSegment request URL segment. 89 | * @param id model/instance ID. 90 | * @param body JSON-type HwWalletObject. 91 | * @return the updated model/instance. 92 | */ 93 | JSONObject partialUpdateHwWalletObject(String urlSegment, String id, String body); 94 | 95 | /** 96 | * Add messages to a HwWalletObject. 97 | * 98 | * @param urlSegment request URL segment. 99 | * @param id model/instance ID. 100 | * @param body JSON-type messageList object. 101 | * @return the updated model/instance. 102 | */ 103 | JSONObject addMessageToHwWalletObject(String urlSegment, String id, String body); 104 | 105 | /** 106 | * Add/remove linked offer IDs to/from a loyalty instance. 107 | * 108 | * @param urlSegment request URL segment. 109 | * @param instanceId instance ID. 110 | * @param body JSON-type LinkedOfferInstanceIds object. 111 | * @return the updated loyalty instance. 112 | */ 113 | JSONObject updateLinkedOffersToLoyaltyInstance(String urlSegment, String instanceId, String body); 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/util/RsaUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.util; 18 | 19 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 20 | 21 | import javax.crypto.Cipher; 22 | import java.security.Key; 23 | import java.security.KeyFactory; 24 | import java.security.PrivateKey; 25 | import java.security.PublicKey; 26 | import java.security.Security; 27 | import java.security.Signature; 28 | import java.security.spec.PKCS8EncodedKeySpec; 29 | import java.security.spec.X509EncodedKeySpec; 30 | import java.util.Base64; 31 | 32 | /** 33 | * RSA-encryption utility class. 34 | * 35 | * @since 2019-12-12 36 | */ 37 | public class RsaUtil { 38 | 39 | /** 40 | * Signature algorithm. 41 | */ 42 | private static final String SIGN_ALGORITHMS256 = "SHA256WithRSA/PSS"; 43 | 44 | private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider(); 45 | 46 | static { 47 | if (Security.getProvider("BC") == null) { 48 | Security.addProvider(new BouncyCastleProvider()); 49 | } 50 | } 51 | 52 | /** 53 | * Sign content. 54 | * 55 | * @param content data to be signed. 56 | * @param privateKey merchant's private key. 57 | * @return the signed value. 58 | */ 59 | public static String sign(String content, String privateKey) { 60 | String charset = "utf-8"; 61 | try { 62 | PKCS8EncodedKeySpec privatePKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)); 63 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 64 | PrivateKey priKey = keyFactory.generatePrivate(privatePKCS8); 65 | 66 | java.security.Signature signatureObj = java.security.Signature.getInstance(SIGN_ALGORITHMS256); 67 | signatureObj.initSign(priKey); 68 | signatureObj.update(content.getBytes(charset)); 69 | 70 | byte[] signed = signatureObj.sign(); 71 | return Base64.getEncoder().encodeToString(signed); 72 | } catch (Exception e) { 73 | throw new IllegalArgumentException("Get signature failed. Error: " + e.getMessage()); 74 | } 75 | } 76 | 77 | /** 78 | * Encrypt bytes. 79 | * 80 | * @param bytes bytes to be encrypted. 81 | * @param publicKey public key. 82 | * @param algorithm encryption algorithm. 83 | * @return the encrypted string. 84 | */ 85 | public static String encrypt(byte[] bytes, String publicKey, String algorithm) throws Exception { 86 | Key key = getPublicKey(publicKey); 87 | Cipher cipher = Cipher.getInstance(algorithm, BOUNCY_CASTLE_PROVIDER); 88 | cipher.init(Cipher.ENCRYPT_MODE, key); 89 | byte[] b1 = cipher.doFinal(bytes); 90 | return Base64.getEncoder().encodeToString(b1); 91 | } 92 | 93 | /** 94 | * Convert a public key string to a PublicKey. 95 | * 96 | * @param key the public key string. 97 | * @return the converted PublicKey. 98 | */ 99 | public static PublicKey getPublicKey(String key) throws Exception { 100 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(key)); 101 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 102 | return keyFactory.generatePublic(keySpec); 103 | } 104 | 105 | /** 106 | * Verify a signature. 107 | * 108 | * @param content content of the signature. 109 | * @param publicKey the public key string. 110 | * @param sign the signature to be verified. 111 | * @return if the signature is valid. 112 | */ 113 | public static boolean verifySignature(String content, String publicKey, String sign) throws Exception { 114 | PublicKey key = getPublicKey(publicKey); 115 | Signature signature = Signature.getInstance(SIGN_ALGORITHMS256); 116 | signature.initVerify(key); 117 | signature.update(content.getBytes()); 118 | return signature.verify(Base64.getDecoder().decode(sign.getBytes())); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/signature/SignatureTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.signature; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | import com.huawei.wallet.util.RsaUtil; 21 | import org.junit.Test; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Collections; 25 | import java.util.Iterator; 26 | import java.util.List; 27 | import java.util.Objects; 28 | 29 | /** 30 | * Test for callback signature validation. 31 | * 32 | * @since 2020-10-09 33 | */ 34 | public class SignatureTest { 35 | 36 | /** 37 | * If your server receive a callback notification request from HMS wallet server, you should verify the 38 | * signature in the request header with Huawei's fixed signature public key. The signature is signed with 39 | * "SHA256WithRSA/PSS" algorithm. This test shows an example of verifying a signature. 40 | */ 41 | @Test 42 | public void verifySignature() throws Exception { 43 | System.out.println("verifySignature begin."); 44 | 45 | // Assume you received a callback notification request with following request body parameters. 46 | JSONObject receivedBody = new JSONObject(); 47 | receivedBody.put("eventId", "469283774166292993"); 48 | receivedBody.put("eventTime", "2020-10-09T03:41:55.694Z"); 49 | receivedBody.put("passNumber", "passNumber1234"); 50 | receivedBody.put("passTypeIdentifier", "hwpass.com.xxx"); 51 | receivedBody.put("eventType", "DELETE_CARD"); 52 | receivedBody.put("sceneType", "THIRD_PARTY_DELETE_CARD"); 53 | receivedBody.put("noticeToken", "1e4dda10e4590dcd66d1c14bfe1505424091f693996d2db885e54ad040723d7c"); 54 | receivedBody.put("pushToken", "asdfghjkl"); 55 | // Convert the parameters into a string in certain format. 56 | String content = toSignString(receivedBody); 57 | 58 | // Assume this is the HMSSign you received in the request header. 59 | String receivedHMSSign = 60 | "g6Ylid2v13ibrGCDITYkms7rOxM9Qmpn2nTQy+MDneCvs8n2AznhdH1BOdZxAFEeNvIqaBejupJJNnHweDixxwQub34pt7Kv0wuW3LI0gtut5jsjEJuF9kfPj/f6W6ZfUgZB8R9j6jGMzqWoa7IRkXpIxpdJgral8aE+QwMG51hrzH8j/7EbPxpQgFyxuxiZimaeKDbgJ2yWIDtnaEVs+6NxLMhz+Vgo0vxEiyo+TEdcpkl0ahMA8XCXGs6lqlbl+G8imlU4+pMvM+IL9ygCbDWgwj6pmfrkDnD/tYVqElE9SIZ79+ShWLNwUgtWFfzo1ckMRWGSdMfwVd+f6boVIQ=="; 61 | 62 | // Huawei's fixed signature public key. 63 | String signPubKey = 64 | "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1+b2/q6KEJfvI65xJLXhPMT8YRUO618zsgaW4pNGZ+r/mwfFC1EOZbcBp7sV0IaxSWeMy0WNyJPSh/JltuiC1R93hfA0Kh3DlaRWaDgJz9VC1b+aPjUOx+uqndOEFiZcKGGnM60YPXfyo7xCDH76/WsWR0G4Ov6MoYQ76RAUT0t+G0oumYGgdLYwx5hJ1ywDKPXszj7A/mKHtWJKiylPIhUK2mLwKR8Y/+3dLNuNomvb7miVgeBFiriwGS1FolQMu433zEugAqRgsiasZAKfVK1BChPmiC812IMS1UPhz1wwpXzzkjQ1YQUGjnbHpooKobeCyctKKgF27F84egpzsQIDAQAB"; 65 | 66 | // Verify signature. 67 | boolean isValid = RsaUtil.verifySignature(content, signPubKey, receivedHMSSign); 68 | 69 | System.out.println("String to be signed: " + content); 70 | System.out.println("Received HMSSign: " + receivedHMSSign); 71 | System.out.println("Is signature valid? " + isValid); 72 | } 73 | 74 | private String toSignString(JSONObject jsonObject) { 75 | List sortedKeys = new ArrayList<>(jsonObject.keySet()); 76 | Collections.sort(sortedKeys); 77 | 78 | StringBuilder buffer = new StringBuilder(); 79 | Iterator iterator = sortedKeys.iterator(); 80 | while (iterator.hasNext()) { 81 | String key = iterator.next(); 82 | Object obj = jsonObject.get(key); 83 | if (!Objects.isNull(obj)) { 84 | buffer.append(key).append("="); 85 | if ((obj instanceof String) || (obj instanceof Integer)) { 86 | buffer.append(obj); 87 | } else if (obj instanceof JSONObject) { 88 | buffer.append(toSignString((JSONObject) obj)); 89 | } 90 | if (iterator.hasNext()) { 91 | buffer.append("&"); 92 | } 93 | } 94 | } 95 | return buffer.toString(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/util/ConfigUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.util; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.InputStreamReader; 23 | import java.io.Reader; 24 | import java.nio.charset.StandardCharsets; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | import java.util.Properties; 28 | 29 | /** 30 | * Methods to load configuration files. 31 | * 32 | * @since 2019-11-06 33 | */ 34 | public final class ConfigUtil { 35 | /** 36 | * Configuration filename. 37 | */ 38 | private final static String SYSTEM_CONFIG = "release.config.properties"; 39 | 40 | /** 41 | * Data folder. 42 | */ 43 | private final static String DATA = "data/"; 44 | 45 | /** 46 | * Singleton pattern instance. 47 | */ 48 | private static ConfigUtil config; 49 | 50 | private Map params; 51 | 52 | private ConfigUtil() { 53 | load(); 54 | } 55 | 56 | /** 57 | * Singleton pattern implementation. 58 | * 59 | * @return the singleton instance. 60 | */ 61 | public static ConfigUtil instants() { 62 | if (null == config) { 63 | config = new ConfigUtil(); 64 | } 65 | return config; 66 | } 67 | 68 | /** 69 | * Load a configuration file. 70 | */ 71 | private void load() { 72 | if (null == params) { 73 | params = new HashMap<>(); 74 | } else { 75 | params.clear(); 76 | } 77 | Properties properties = new Properties(); 78 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream(SYSTEM_CONFIG); 79 | try { 80 | properties.load(inputStream); 81 | for (Object key : properties.keySet()) { 82 | if (null != key && !"".equals(key.toString())) { 83 | String value = properties.getProperty(key.toString()); 84 | params.put(key.toString().trim(), value.trim()); 85 | } 86 | } 87 | } catch (IOException e) { 88 | throw new IllegalArgumentException("load " + SYSTEM_CONFIG + " failed."); 89 | } 90 | } 91 | 92 | /** 93 | * Get a specific value in a configuration file by its key. 94 | * 95 | * @param key the key to the value. 96 | * @return the value string. 97 | */ 98 | public String getValue(String key) { 99 | return params.get(key); 100 | } 101 | 102 | /** 103 | * Read a file in the test/resources/data folder. 104 | * 105 | * @param fileName file name 106 | * @return the value string. 107 | */ 108 | public static String readFile(String fileName) { 109 | InputStream inputStream = ConfigUtil.class.getClassLoader().getResourceAsStream(DATA + fileName); 110 | if (inputStream == null) { 111 | throw new IllegalArgumentException("File " + fileName + "not found."); 112 | } 113 | Reader reader = null; 114 | BufferedReader bufferedReader = null; 115 | StringBuilder sb = new StringBuilder(); 116 | try { 117 | reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); 118 | bufferedReader = new BufferedReader(reader); 119 | String line; 120 | while ((line = bufferedReader.readLine()) != null) { 121 | sb.append(line); 122 | } 123 | } catch (IOException e) { 124 | throw new IllegalStateException("Read file " + fileName + " failed."); 125 | } finally { 126 | try { 127 | if (null != bufferedReader) { 128 | bufferedReader.close(); 129 | } 130 | if (null != reader) { 131 | reader.close(); 132 | } 133 | inputStream.close(); 134 | } catch (IOException e) { 135 | throw new IllegalArgumentException("File " + fileName + " close failed."); 136 | } 137 | } 138 | return sb.toString(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/jwe/JweTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.jwe; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | import com.huawei.wallet.util.ConfigUtil; 21 | import com.huawei.wallet.util.JweUtil; 22 | import org.junit.Test; 23 | 24 | import java.io.UnsupportedEncodingException; 25 | import java.net.URLEncoder; 26 | 27 | /** 28 | * Tests for generating JWE and thin JWE. 29 | * 30 | * @since 2020-06-12 31 | */ 32 | public class JweTest { 33 | /** 34 | * Generate a JWE. This JWE contains full instance information. It's used to add a new instance to HMS wallet serve 35 | * and bind it to a user. You should generate a JWE with an instance that has not been added to HMS wallet server. 36 | */ 37 | @Test 38 | public void generateJWEToAddInstanceAndBindUser() { 39 | System.out.println("generateJWEToAddPassAndBindUser begin.\n"); 40 | 41 | // This is the app ID registered on Huawei AGC website. 42 | String appId = ConfigUtil.instants().getValue("gw.appid"); 43 | // Read a new pass instance. 44 | JSONObject newInstance = JSONObject.parseObject(ConfigUtil 45 | .readFile("Replace with the instance JSON file to be created. For example: EventTicketInstance.json")); 46 | newInstance.put("iss", appId); 47 | String payload = newInstance.toJSONString(); 48 | 49 | // You generated a pair of RSA keys while applying for services on AGC. Use that private key here. 50 | String jweSignPrivateKey = ConfigUtil.instants().getValue("servicePrivateKey"); 51 | 52 | // Generate a JWE. 53 | String jwe = JweUtil.generateJwe(jweSignPrivateKey, payload); 54 | System.out.println("JWE String: " + jwe + "\n"); 55 | 56 | System.out.println("JWE link for browser: " + ConfigUtil.instants().getValue("walletWebsiteBaseUrl") 57 | + "?content=" + URLEncoder.encode(jwe)); 58 | } 59 | 60 | /** 61 | * Generate a thin JWE. This JWEs contains only instanceId information. It's used to bind an existing instance 62 | * to a user. You should generate a thin JWE with an instanceId that has already been added to HMS wallet server. 63 | */ 64 | @Test 65 | public void generateThinJWEToBindUser() { 66 | System.out.println("generateThinJWEToBindUser begin.\n"); 67 | 68 | generateThinJWEToBindUser("Replace with the instance ID to be bond. For example: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 69 | } 70 | 71 | public void generateThinJWEToBindUser(String instanceId) { 72 | System.out.println("generateThinJWEToBindUser with instanceId begin.\n"); 73 | 74 | // This is the app ID registered on Huawei AGC website. 75 | String appId = ConfigUtil.instants().getValue("gw.appid"); 76 | // Bind existing pass instances to a user. Construct a list of instance IDs to be bound. 77 | String instanceIdListStr = "{\"instanceIds\": [\""+ instanceId + "\"]}"; 78 | JSONObject instanceIdList = JSONObject.parseObject(instanceIdListStr); 79 | instanceIdList.put("iss", appId); 80 | String payload = instanceIdList.toJSONString(); 81 | 82 | // You generated a pair of RSA keys while applying for services on AGC. Use that private key here. 83 | String jweSignPrivateKey = ConfigUtil.instants().getValue("servicePrivateKey"); 84 | 85 | // Generate a thin JWE. 86 | String jwe = JweUtil.generateJwe(jweSignPrivateKey, payload); 87 | System.out.println("JWE String: " + jwe + "\n"); 88 | try { 89 | // 1.If you access with website, such as Chrome Web browser, IE, Microsoft Edge; please encode jwe by URLEncoder.encode(jwe, "UTF-8"); 90 | // 2.If you access with android mobile phone and interact with Huawei Wallet Server directly; please do not encode it; 91 | // 3.If you access with android mobile phone and pass jwe to Huawei Pay Application by android schema; please encode jwe by URLEncoder.encode(jwe, "UTF-8"); 92 | String jweEncoded = URLEncoder.encode(jwe, "UTF-8"); 93 | System.out.println("JWE String after encode: " + jweEncoded + "\n"); 94 | System.out.println("JWE link for browser: " + ConfigUtil.instants().getValue("walletWebsiteBaseUrl") 95 | + "?content=" + jweEncoded); 96 | } catch (UnsupportedEncodingException e) { 97 | System.out.println("Encode JWE String error."); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/stdcarkey/StdCarKeyModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.stdcarkey; 18 | 19 | import com.alibaba.fastjson.JSONArray; 20 | import com.alibaba.fastjson.JSONObject; 21 | import com.huawei.wallet.hms.ServerApiService; 22 | import com.huawei.wallet.hms.ServerApiServiceImpl; 23 | import com.huawei.wallet.util.ConfigUtil; 24 | import com.huawei.wallet.util.HwWalletObjectUtil; 25 | import org.junit.Test; 26 | 27 | /** 28 | * Std car key model tests. 29 | * 30 | * @since 2021-05-27 31 | */ 32 | public class StdCarKeyModelTest { 33 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 34 | 35 | /** 36 | * Create a new std car key model. 37 | * Each std car key model indicates a style of std car key passes. 38 | * POST http://XXX/hmspass/v2/key_stdcar/model 39 | */ 40 | @Test 41 | public void createStdCarKeyModel() { 42 | System.out.println("createStdCarKeyModel begin."); 43 | 44 | // Read a std car key model from a JSON file. 45 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("StdCarKeyModel.json")); 46 | 47 | // Validate parameters. 48 | HwWalletObjectUtil.validateModel(model); 49 | 50 | // Post the new std car key model to HMS wallet server. 51 | String urlSegment = "/v2/key_stdcar/model"; 52 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 53 | System.out.println("Posted std car key model: " + JSONObject.toJSONString(responseModel)); 54 | } 55 | 56 | /** 57 | * Get a std car key model by its model ID. 58 | * Run the "createStdCarKeyModel" test before running this test. 59 | * GET http://xxx/hmspass/v2/key_stdcar/model/{modelId} 60 | */ 61 | @Test 62 | public void getStdCarKeyModel() { 63 | System.out.println("getStdCarKeyModel begin."); 64 | 65 | // ID of the std car key model you want to get. 66 | String modelId = "xxxxxxx"; 67 | 68 | // Get the std car key model. 69 | String urlSegment = "/v2/key_stdcar/model/"; 70 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 71 | System.out.println("Corresponding std car key model: " + JSONObject.toJSONString(responseModel)); 72 | } 73 | 74 | /** 75 | * Get std car key models belonging to a specific appId. 76 | * Run the "createStdCarKeyModel" test before running this test. 77 | * GET http://xxx/hmspass/v2/key_stdcar/model?session=XXX&pageSize=XXX 78 | */ 79 | @Test 80 | public void getStdCarKeyModelList() { 81 | System.out.println("getStdCarKeyModelList begin."); 82 | 83 | // Get a list of std car key models. 84 | String urlSegment = "/v2/key_stdcar/model"; 85 | 86 | JSONArray models = serverApiService.getModels(urlSegment, 5); 87 | System.out.println("Total models count: " + models.size()); 88 | System.out.println("Models list: " + models.toJSONString()); 89 | } 90 | 91 | /** 92 | * Overwrite a std car key model. 93 | * Run the "createStdCarKeyModel" test before running this test. 94 | * PUT http://xxx/hmspass/v2/key_stdcar/model/{modelId} 95 | */ 96 | @Test 97 | public void fullUpdateStdCarKeyModel() { 98 | System.out.println("fullUpdateStdCarKeyModel begin."); 99 | 100 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 101 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateStdCarKeyModel.json")); 102 | 103 | // Validate parameters. 104 | HwWalletObjectUtil.validateModel(model); 105 | 106 | // Update the std car key model. 107 | String urlSegment = "/v2/key_stdcar/model/"; 108 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 109 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 110 | System.out.println("Updated std car key model: " + JSONObject.toJSONString(responseModel)); 111 | } 112 | 113 | /** 114 | * Update a std car key model. 115 | * Run the "createStdCarKeyModel" test before running this test. 116 | * PATCH http://xxx/hmspass/v2/key_stdcar/model/{modelId} 117 | */ 118 | @Test 119 | public void partialUpdateStdCarKeyModel() { 120 | System.out.println("partialUpdateStdCarKeyModel begin."); 121 | 122 | // ID of the std car key model you want to update. 123 | String modelId = "xxxxxxx"; 124 | 125 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 126 | String modelStr = ConfigUtil.readFile("PartialUpdateStdCarKeyModel.json"); 127 | 128 | // Update the std car key model. 129 | String urlSegment = "/v2/key_stdcar/model/"; 130 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 131 | System.out.println("Updated std car key model: " + JSONObject.toJSONString(responseModel)); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/util/HwWalletObjectUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.util; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | import org.springframework.util.StringUtils; 21 | 22 | import java.time.Instant; 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.Date; 26 | import java.util.List; 27 | import java.util.Locale; 28 | 29 | /** 30 | * HwWalletObject utility class. 31 | * 32 | * @since 2019-12-4 33 | */ 34 | public class HwWalletObjectUtil { 35 | 36 | private static final String STATE_ACTIVE = "active"; 37 | 38 | private static final String STATE_INACTIVE = "inactive"; 39 | 40 | private static final String STATE_COMPLETED = "completed"; 41 | 42 | private static final String STATE_EXPIRED = "expired"; 43 | 44 | private static final List STATE_TYPE_LIST = 45 | new ArrayList<>(Arrays.asList(STATE_ACTIVE, STATE_INACTIVE, STATE_COMPLETED, STATE_EXPIRED)); 46 | 47 | /** 48 | * Validate a model. 49 | * 50 | * @param model the pass model. 51 | */ 52 | public static void validateModel(JSONObject model) { 53 | if (model != null) { 54 | checkRequiredParams(model, "passTypeIdentifier", 64); 55 | checkRequiredParams(model, "passStyleIdentifier", 64); 56 | checkRequiredParams(model, "organizationName", 64); 57 | checkRequiredParams(model, "passVersion", 64); 58 | } else { 59 | throw new IllegalArgumentException("The model is empty"); 60 | } 61 | } 62 | 63 | /** 64 | * Validate an instance. 65 | * 66 | * @param instance the instance. 67 | */ 68 | public static void validateInstance(JSONObject instance) { 69 | if (instance != null) { 70 | checkRequiredParams(instance, "passTypeIdentifier", 64); 71 | checkRequiredParams(instance, "passStyleIdentifier", 64); 72 | checkRequiredParams(instance, "organizationPassId", 64); 73 | checkRequiredParams(instance, "serialNumber", 64); 74 | validateStatusDate(instance); 75 | } else { 76 | throw new IllegalArgumentException("The instance is empty."); 77 | } 78 | } 79 | 80 | /** 81 | * Check a required attribute. 82 | * 83 | * @param jsonObject the object to be checked. 84 | * @param attrName the attribute's name. 85 | * @param maxLen the attribute's maximum length. 86 | */ 87 | private static void checkRequiredParams(JSONObject jsonObject, String attrName, int maxLen) { 88 | if (!jsonObject.containsKey(attrName) || !(jsonObject.get(attrName) instanceof String)) { 89 | throw new IllegalArgumentException(attrName + " is missing."); 90 | } 91 | if (jsonObject.getString(attrName).length() > maxLen) { 92 | throw new IllegalArgumentException(attrName + " exceeds maximum length."); 93 | } 94 | } 95 | 96 | /** 97 | * Check if the Status of an instance is legal. 98 | * 99 | * @param instance the instance. 100 | */ 101 | private static void validateStatusDate(JSONObject instance) { 102 | JSONObject fields = instance.getJSONObject("fields"); 103 | if (fields == null || fields.getJSONObject("status") == null) { 104 | return; 105 | } 106 | String state = fields.getJSONObject("status").getString("state"); 107 | String effectTime = fields.getJSONObject("status").getString("effectTime"); 108 | String expireTime = fields.getJSONObject("status").getString("expireTime"); 109 | if (!StringUtils.isEmpty(state)) { 110 | if (!STATE_TYPE_LIST.contains(state.toLowerCase(Locale.getDefault()))) { 111 | throw new IllegalArgumentException("state is invalid."); 112 | } 113 | } 114 | 115 | if ((StringUtils.isEmpty(effectTime) && !StringUtils.isEmpty(expireTime)) 116 | || (!StringUtils.isEmpty(effectTime) && StringUtils.isEmpty(expireTime))) { 117 | throw new IllegalArgumentException("effectTime and expireTime should be both exist or not exist."); 118 | } 119 | 120 | if (StringUtils.isEmpty(expireTime)) { 121 | return; 122 | } 123 | 124 | Date statusEffectTime; 125 | Date statusExpireTime; 126 | 127 | statusEffectTime = getLocalTimeByUtcString(effectTime); 128 | statusExpireTime = getLocalTimeByUtcString(expireTime); 129 | 130 | if ((statusExpireTime.before(new Date())) || (statusExpireTime.before(statusEffectTime))) { 131 | throw new IllegalArgumentException("expireTime must be later than effectTime and current time."); 132 | } 133 | } 134 | 135 | /** 136 | * Convert UTC to local time. 137 | * 138 | * @param utcTimeString the UTC string. 139 | * @return the local time in Date type. 140 | */ 141 | private static Date getLocalTimeByUtcString(String utcTimeString) { 142 | Date date = null; 143 | 144 | if (utcTimeString != null) { 145 | try { 146 | date = Date.from(Instant.parse(utcTimeString)); 147 | } catch (Exception e) { 148 | throw new IllegalArgumentException("Invalid time format. Error: " + e.getMessage()); 149 | } 150 | } 151 | return date; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /serverdemo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/stdcarkey/StdCarKeyInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.stdcarkey; 18 | 19 | import com.alibaba.fastjson.JSONArray; 20 | import com.alibaba.fastjson.JSONObject; 21 | import com.huawei.wallet.hms.ServerApiService; 22 | import com.huawei.wallet.hms.ServerApiServiceImpl; 23 | import com.huawei.wallet.hms.jwe.JweTest; 24 | import com.huawei.wallet.util.ConfigUtil; 25 | import com.huawei.wallet.util.HwWalletObjectUtil; 26 | import org.junit.Test; 27 | 28 | /** 29 | * Std car key instance tests. 30 | * 31 | * @since 2021-05-27 32 | */ 33 | public class StdCarKeyInstanceTest { 34 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 35 | 36 | /** 37 | * Add a std car key instance to HMS wallet server. 38 | * Run the "createStdCarKeyInstance" test before running this test. 39 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 40 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 41 | * POST http://XXX/hmspass/v2/key_stdcar/instance 42 | */ 43 | @Test 44 | public void addStdCarKeyInstance() { 45 | System.out.println("addStdCarKeyInstance begin."); 46 | 47 | // Read a std car key instance from a JSON file. 48 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("StdCarKeyInstance.json")); 49 | 50 | // Validate parameters. 51 | HwWalletObjectUtil.validateInstance(instance); 52 | 53 | // Post the new std car key instance to HMS wallet server. 54 | String urlSegment = "/v2/key_stdcar/instance"; 55 | JSONObject responseInstance = 56 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 57 | System.out.println("Posted std car key instance: " + JSONObject.toJSONString(responseInstance)); 58 | 59 | if (responseInstance.containsKey("serialNumber")) { 60 | String serialNumber = responseInstance.getString("serialNumber"); 61 | JweTest test = new JweTest(); 62 | test.generateThinJWEToBindUser(serialNumber); 63 | } 64 | } 65 | 66 | /** 67 | * Get a std car key instance by its instance ID. 68 | * Run the "createStdCarKeyInstance" test before running this test. 69 | * GET http://xxx/hmspass/v2/key_stdcar/instance/{instanceId} 70 | */ 71 | @Test 72 | public void getStdCarKeyInstance() { 73 | System.out.println("getStdCarKeyInstance begin."); 74 | 75 | // ID of the std car key instance you want to get. 76 | String instanceId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 77 | 78 | // Get the std car key instance. 79 | String urlSegment = "/v2/key_stdcar/instance/"; 80 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 81 | System.out.println("Corresponding std car key instance: " + JSONObject.toJSONString(responseInstance)); 82 | } 83 | 84 | /** 85 | * Get std car key instance belonging to a specific std car key model. 86 | * Run the "createStdCarKeyInstance" test before running this test. 87 | * GET http://xxx/hmspass/v2/key_stdcar/instance?modelId=XXX&session=XXX&pageSize=XXX 88 | */ 89 | @Test 90 | public void getStdCarKeyInstanceList() { 91 | System.out.println("getStdCarKeyyInstanceList begin."); 92 | 93 | // Model ID of std car key instances you want to get. 94 | String modelId = "xxxxx"; 95 | 96 | // Get a list of std car key instances. 97 | String urlSegment = "/v2/key_stdcar/instance"; 98 | 99 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 100 | System.out.println("Total instances count: " + instances.size()); 101 | System.out.println("Instances list: " + instances.toJSONString()); 102 | } 103 | 104 | /** 105 | * Overwrite a std car key instance. 106 | * Run the "createStdCarKeyInstance" test before running this test. 107 | * PUT http://xxx/hmspass/v2/key_stdcar/instance/{instanceId} 108 | */ 109 | @Test 110 | public void fullUpdateStdCarKeyInstance() { 111 | System.out.println("fullUpdateStdCarKeyInstance begin."); 112 | 113 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 114 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateStdCarKeyInstance.json")); 115 | 116 | // Validate parameters. 117 | HwWalletObjectUtil.validateInstance(instance); 118 | 119 | // Update the std car key instance. 120 | String urlSegment = "/v2/key_stdcar/instance/"; 121 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 122 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 123 | System.out.println("Updated std car key instance: " + JSONObject.toJSONString(responseInstance)); 124 | } 125 | 126 | /** 127 | * Update a std car key instance. 128 | * Run the "createStdCarKeyInstance" test before running this test. 129 | * PATCH http://xxx/hmspass/v2/key_stdcar/instance/{instanceId} 130 | */ 131 | @Test 132 | public void partialUpdateStdCarKeyInstance() { 133 | System.out.println("partialUpdateStdCarKeyInstance begin."); 134 | 135 | // ID of the std car key instance you want to update. 136 | String instanceId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 137 | 138 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 139 | String instanceStr = ConfigUtil.readFile("PartialUpdateStdCarKeyInstance.json"); 140 | 141 | // Update the std car key instance. 142 | String urlSegment = "/v2/key_stdcar/instance/"; 143 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 144 | System.out.println("Updated std car key instance: " + JSONObject.toJSONString(responseInstance)); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/offer/OfferModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.offer; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Offer model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class OfferModelTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new offer model. 39 | * Each offer model indicates a style of offer passes. 40 | * POST http://XXX/hmspass/v1/offer/model 41 | */ 42 | @Test 43 | public void createOfferModel() { 44 | System.out.println("createOfferModel begin."); 45 | 46 | // Read an offer model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("OfferModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new offer model to HMS wallet server. 53 | String urlSegment = "/v1/offer/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted offer model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get an offer model by its model ID. 60 | * Run the "createOfferModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/offer/model/{modelId} 62 | */ 63 | @Test 64 | public void getOfferModel() { 65 | System.out.println("getOfferModel begin."); 66 | 67 | // ID of the offer model you want to get. 68 | String modelId = "OfferTestModel"; 69 | 70 | // Get the offer model. 71 | String urlSegment = "/v1/offer/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding offer model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get offer models belonging to a specific appId. 78 | * Run the "createOfferModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/offer/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getOfferModelList() { 83 | System.out.println("getOfferModelList begin."); 84 | 85 | // Get a list of offer models. 86 | String urlSegment = "/v1/offer/model"; 87 | 88 | JSONArray models = serverApiService.getModels(urlSegment, 5); 89 | System.out.println("Total models count: " + models.size()); 90 | System.out.println("Models list: " + models.toJSONString()); 91 | } 92 | 93 | /** 94 | * Overwrite an offer model. 95 | * Run the "createOfferModel" test before running this test. 96 | * PUT http://xxx/hmspass/v1/offer/model/{modelId} 97 | */ 98 | @Test 99 | public void fullUpdateOfferModel() { 100 | System.out.println("fullUpdateOfferModel begin."); 101 | 102 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 103 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateOfferModel.json")); 104 | 105 | // Validate parameters. 106 | HwWalletObjectUtil.validateModel(model); 107 | 108 | // Update the offer model. 109 | String urlSegment = "/v1/offer/model/"; 110 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 111 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 112 | System.out.println("Updated offer model: " + JSONObject.toJSONString(responseModel)); 113 | } 114 | 115 | /** 116 | * Update an offer model. 117 | * Run the "createOfferModel" test before running this test. 118 | * PATCH http://xxx/hmspass/v1/offer/model/{modelId} 119 | */ 120 | @Test 121 | public void partialUpdateOfferModel() { 122 | System.out.println("partialUpdateOfferModel begin."); 123 | 124 | // ID of the offer model you want to update. 125 | String modelId = "OfferTestModel"; 126 | 127 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 128 | String modelStr = ConfigUtil.readFile("PartialUpdateOfferModel.json"); 129 | 130 | // Update the offer model. 131 | String urlSegment = "/v1/offer/model/"; 132 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 133 | System.out.println("Updated offer model: " + JSONObject.toJSONString(responseModel)); 134 | } 135 | 136 | /** 137 | * Add messages to an offer model. 138 | * Run the "createOfferModel" test before running this test. 139 | * POST http://xxx/hmspass/v1/offer/model/{modelId}/addMessage 140 | */ 141 | @Test 142 | public void addMessageToOfferModel() { 143 | System.out.println("addMessageToOfferModel begin."); 144 | 145 | // ID of the offer model you want to update. 146 | String modelId = "OfferTestModel"; 147 | 148 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 149 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 150 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 151 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 152 | // messages at a time. 153 | 154 | // Read messages from a JSON file. 155 | String messagesStr = ConfigUtil.readFile("Messages.json"); 156 | 157 | // Add messages to the offer model. 158 | String urlSegment = "/v1/offer/model/"; 159 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 160 | System.out.println("Updated offer model: " + JSONObject.toJSONString(responseModel)); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/flight/FlightModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.flight; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Flight model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class FlightModelTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new flight model. 39 | * Each flight model indicates a style of flight passes. 40 | * POST http://XXX/hmspass/v1/flight/model 41 | */ 42 | @Test 43 | public void createFlightModel() { 44 | System.out.println("createFlightModel begin."); 45 | 46 | // Read a flight model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FlightModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new flight model to HMS wallet server. 53 | String urlSegment = "/v1/flight/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted flight model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get a flight model by its model ID. 60 | * Run the "createFlightModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/flight/model/{modelId} 62 | */ 63 | @Test 64 | public void getFlightModel() { 65 | System.out.println("getFlightModel begin."); 66 | 67 | // ID of the flight model you want to get. 68 | String modelId = "FlightTestModel"; 69 | 70 | // Get the flight model. 71 | String urlSegment = "/v1/flight/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding flight model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get flight models belonging to a specific appId. 78 | * Run the "createFlightModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/flight/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getFlightModelList() { 83 | System.out.println("getFlightModelList begin."); 84 | 85 | // Get a list of flight models. 86 | String urlSegment = "/v1/flight/model"; 87 | JSONArray models = serverApiService.getModels(urlSegment, 5); 88 | System.out.println("Total models count: " + models.size()); 89 | System.out.println("Models list: " + models.toJSONString()); 90 | } 91 | 92 | /** 93 | * Overwrite a flight model. 94 | * Run the "createFlightModel" test before running this test. 95 | * PUT http://xxx/hmspass/v1/flight/model/{modelId} 96 | */ 97 | @Test 98 | public void fullUpdateFlightModel() { 99 | System.out.println("fullUpdateFlightModel begin."); 100 | 101 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 102 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateFlightModel.json")); 103 | 104 | // Validate parameters. 105 | HwWalletObjectUtil.validateModel(model); 106 | 107 | // Update the flight model. 108 | String urlSegment = "/v1/flight/model/"; 109 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 110 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 111 | System.out.println("Updated flight model: " + JSONObject.toJSONString(responseModel)); 112 | } 113 | 114 | /** 115 | * Update a flight model. 116 | * Run the "createFlightModel" test before running this test. 117 | * PATCH http://xxx/hmspass/v1/flight/model/{modelId} 118 | */ 119 | @Test 120 | public void partialUpdateFlightModel() { 121 | System.out.println("partialUpdateFlightModel begin."); 122 | 123 | // ID of the flight model you want to update. 124 | String modelId = "FlightTestModel"; 125 | 126 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 127 | String modelStr = ConfigUtil.readFile("PartialUpdateFlightModel.json"); 128 | 129 | // Update the flight model. 130 | String urlSegment = "/v1/flight/model/"; 131 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 132 | System.out.println("Updated flight model: " + JSONObject.toJSONString(responseModel)); 133 | } 134 | 135 | /** 136 | * Add messages to a flight model. 137 | * Run the "createFlightModel" test before running this test. 138 | * POST http://xxx/hmspass/v1/flight/model/{modelId}/addMessage 139 | */ 140 | @Test 141 | public void addMessageToFlightModel() { 142 | System.out.println("addMessageToFlightModel begin."); 143 | 144 | // ID of the flight model you want to update. 145 | String modelId = "FlightTestModel"; 146 | 147 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 148 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 149 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 150 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 151 | // messages at a time. 152 | 153 | // Read messages from a JSON file. 154 | String messagesStr = ConfigUtil.readFile("Messages.json"); 155 | 156 | // Add messages to the flight model. 157 | String urlSegment = "/v1/flight/model/"; 158 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 159 | System.out.println("Updated flight model: " + JSONObject.toJSONString(responseModel)); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/loyalty/LoyaltyModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.loyalty; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Loyalty model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class LoyaltyModelTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new loyalty model. 39 | * Each loyalty model indicates a style of loyalty passes. 40 | * POST http://XXX/hmspass/v1/loyalty/model 41 | */ 42 | @Test 43 | public void createLoyaltyModel() { 44 | System.out.println("createLoyaltyModel begin."); 45 | 46 | // Read a loyalty model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("LoyaltyModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new loyalty model to HMS wallet server. 53 | String urlSegment = "/v1/loyalty/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted loyalty model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get a loyalty model by its model ID. 60 | * Run the "createLoyaltyModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/loyalty/model/{modelId} 62 | */ 63 | @Test 64 | public void getLoyaltyModel() { 65 | System.out.println("getLoyaltyModel begin."); 66 | 67 | // ID of the loyalty model you want to get. 68 | String modelId = "LoyaltyTestModel"; 69 | 70 | // Get the loyalty model. 71 | String urlSegment = "/v1/loyalty/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding loyalty model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get loyalty models belonging to a specific appId. 78 | * Run the "createLoyaltyModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/loyalty/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getLoyaltyModelList() { 83 | System.out.println("getLoyaltyModelList begin."); 84 | 85 | // Get a list of loyalty models. 86 | String urlSegment = "/v1/loyalty/model"; 87 | 88 | JSONArray models = serverApiService.getModels(urlSegment, 5); 89 | System.out.println("Total models count: " + models.size()); 90 | System.out.println("Models list: " + models.toJSONString()); 91 | } 92 | 93 | /** 94 | * Overwrite a loyalty model. 95 | * Run the "createLoyaltyModel" test before running this test. 96 | * PUT http://xxx/hmspass/v1/loyalty/model/{modelId} 97 | */ 98 | @Test 99 | public void fullUpdateLoyaltyModel() { 100 | System.out.println("fullUpdateLoyaltyModel begin."); 101 | 102 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 103 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateLoyaltyModel.json")); 104 | 105 | // Validate parameters. 106 | HwWalletObjectUtil.validateModel(model); 107 | 108 | // Update the loyalty model. 109 | String urlSegment = "/v1/loyalty/model/"; 110 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 111 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 112 | System.out.println("Updated loyalty model: " + JSONObject.toJSONString(responseModel)); 113 | } 114 | 115 | /** 116 | * Update a loyalty model. 117 | * Run the "createLoyaltyModel" test before running this test. 118 | * PATCH http://xxx/hmspass/v1/loyalty/model/{modelId} 119 | */ 120 | @Test 121 | public void partialUpdateLoyaltyModel() { 122 | System.out.println("partialUpdateLoyaltyModel begin."); 123 | 124 | // ID of the loyalty model you want to update. 125 | String modelId = "LoyaltyTestModel"; 126 | 127 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 128 | String modelStr = ConfigUtil.readFile("PartialUpdateLoyaltyModel.json"); 129 | 130 | // Update the loyalty model. 131 | String urlSegment = "/v1/loyalty/model/"; 132 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 133 | System.out.println("Updated loyalty model: " + JSONObject.toJSONString(responseModel)); 134 | } 135 | 136 | /** 137 | * Add messages to a loyalty model. 138 | * Run the "createLoyaltyModel" test before running this test. 139 | * POST http://xxx/hmspass/v1/loyalty/model/{modelId}/addMessage 140 | */ 141 | @Test 142 | public void addMessageToLoyaltyModel() { 143 | System.out.println("addMessageToLoyaltyModel begin."); 144 | 145 | // ID of the loyalty model you want to update. 146 | String modelId = "LoyaltyTestModel"; 147 | 148 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 149 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 150 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 151 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 152 | // messages at a time. 153 | 154 | // Read messages from a JSON file. 155 | String messagesStr = ConfigUtil.readFile("Messages.json"); 156 | 157 | // Add messages to the loyalty model. 158 | String urlSegment = "/v1/loyalty/model/"; 159 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 160 | System.out.println("Updated loyalty model: " + JSONObject.toJSONString(responseModel)); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/transit/TransitModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.transit; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Transit model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class TransitModelTest { 35 | private ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new transit model. 39 | * Each transit model indicates a style of transit passes. 40 | * POST http://XXX/hmspass/v1/transit/model 41 | */ 42 | @Test 43 | public void createTransitModel() { 44 | System.out.println("createTransitModel begin."); 45 | 46 | // Read a transit model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("TransitModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new transit model to HMS wallet server. 53 | String urlSegment = "/v1/transit/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted transit model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get a transit model by its model ID. 60 | * Run the "createTransitModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/transit/model/{modelId} 62 | */ 63 | @Test 64 | public void getTransitModel() { 65 | System.out.println("getTransitModel begin."); 66 | 67 | // ID of the transit model you want to get. 68 | String modelId = "TransitTestModel"; 69 | 70 | // Get the transit model. 71 | String urlSegment = "/v1/transit/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding transit model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get transit model belonging to a specific appId. 78 | * Run the "createTransitModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/transit/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getTransitModelList() { 83 | System.out.println("getTransitModelList begin."); 84 | 85 | // Get a list of transit models. 86 | String urlSegment = "/v1/transit/model"; 87 | 88 | JSONArray models = serverApiService.getModels(urlSegment, 5); 89 | System.out.println("Total models count: " + models.size()); 90 | System.out.println("Models list: " + models.toJSONString()); 91 | } 92 | 93 | /** 94 | * Overwrite a transit model. 95 | * Run the "createTransitModel" test before running this test. 96 | * PUT http://xxx/hmspass/v1/transit/model/{modelId} 97 | */ 98 | @Test 99 | public void fullUpdateTransitModel() { 100 | System.out.println("fullUpdateTransitModel begin."); 101 | 102 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 103 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateTransitModel.json")); 104 | 105 | // Validate parameters. 106 | HwWalletObjectUtil.validateModel(model); 107 | 108 | // Update the transit model. 109 | String urlSegment = "/v1/transit/model/"; 110 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 111 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 112 | System.out.println("Updated transit model: " + JSONObject.toJSONString(responseModel)); 113 | } 114 | 115 | /** 116 | * Update a transit model. 117 | * Run the "createTransitModel" test before running this test. 118 | * PATCH http://xxx/hmspass/v1/transit/model/{modelId} 119 | */ 120 | @Test 121 | public void partialUpdateTransitModel() { 122 | System.out.println("partialUpdateTransitModel begin."); 123 | 124 | // ID of the transit model you want to update. 125 | String modelId = "TransitTestModel"; 126 | 127 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 128 | String modelStr = ConfigUtil.readFile("PartialUpdateTransitModel.json"); 129 | 130 | // Update the transit model. 131 | String urlSegment = "/v1/transit/model/"; 132 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 133 | System.out.println("Updated transit model: " + JSONObject.toJSONString(responseModel)); 134 | } 135 | 136 | /** 137 | * Add messages to a transit model. 138 | * Run the "createTransitModel" test before running this test. 139 | * POST http://xxx/hmspass/v1/transit/model/{modelId}/addMessage 140 | */ 141 | @Test 142 | public void addMessageToTransitModel() { 143 | System.out.println("addMessageToTransitModel begin."); 144 | 145 | // ID of the transit model you want to update. 146 | String modelId = "TransitTestModel"; 147 | 148 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 149 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 150 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 151 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 152 | // messages at a time. 153 | 154 | // Read messages from a JSON file. 155 | String messagesStr = ConfigUtil.readFile("Messages.json"); 156 | 157 | // Add messages to the transit model. 158 | String urlSegment = "/v1/transit/model/addMessage"; 159 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 160 | System.out.println("Updated transit model: " + JSONObject.toJSONString(responseModel)); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/giftcard/GiftCardModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.giftcard; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Gift card model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class GiftCardModelTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new gift card model. 39 | * Each gift card model indicates a style of gift card passes. 40 | * POST http://XXX/hmspass/v1/giftcard/model 41 | */ 42 | @Test 43 | public void createGiftCardModel() { 44 | System.out.println("createGiftCardModel begin."); 45 | 46 | // Read a gift card model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("GiftCardModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new gift card model to HMS wallet server. 53 | String urlSegment = "/v1/giftcard/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted gift card model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get a gift card model by its model ID. 60 | * Run the "createGiftCardModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/giftcard/model/{modelId} 62 | */ 63 | @Test 64 | public void getGiftCardModel() { 65 | System.out.println("getGiftCardModel begin."); 66 | 67 | // ID of the gift card model you want to get. 68 | String modelId = "GiftCardTestModel"; 69 | 70 | // Get the gift card model. 71 | String urlSegment = "/v1/giftcard/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding gift card model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get gift card models belonging to a specific appId. 78 | * Run the "createGiftCardModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/giftcard/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getGiftCardModelList() { 83 | System.out.println("getGiftCardModelList begin."); 84 | 85 | // Get a list of gift card models. 86 | String urlSegment = "/v1/giftcard/model"; 87 | 88 | JSONArray models = serverApiService.getModels(urlSegment, 5); 89 | System.out.println("Total models count: " + models.size()); 90 | System.out.println("Models list: " + models.toJSONString()); 91 | } 92 | 93 | /** 94 | * Overwrite a gift card model. 95 | * Run the "createGiftCardModel" test before running this test. 96 | * PUT http://xxx/hmspass/v1/giftcard/model/{modelId} 97 | */ 98 | @Test 99 | public void fullUpdateGiftCardModel() { 100 | System.out.println("fullUpdateGiftCardModel begin."); 101 | 102 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 103 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateGiftCardModel.json")); 104 | 105 | // Validate parameters. 106 | HwWalletObjectUtil.validateModel(model); 107 | 108 | // Update the gift card model. 109 | String urlSegment = "/v1/giftcard/model/"; 110 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 111 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 112 | System.out.println("Updated gift card model: " + JSONObject.toJSONString(responseModel)); 113 | } 114 | 115 | /** 116 | * Update a gift card model. 117 | * Run the "createGiftCardModel" test before running this test. 118 | * PATCH http://xxx/hmspass/v1/giftcard/model/{modelId} 119 | */ 120 | @Test 121 | public void partialUpdateGiftCardModel() { 122 | System.out.println("partialUpdateGiftCardModel begin."); 123 | 124 | // ID of the gift card model you want to update. 125 | String modelId = "GiftCardTestModel"; 126 | 127 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 128 | String modelStr = ConfigUtil.readFile("PartialUpdateGiftCardModel.json"); 129 | 130 | // Update the gift card model. 131 | String urlSegment = "/v1/giftcard/model/"; 132 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 133 | System.out.println("Updated gift card model: " + JSONObject.toJSONString(responseModel)); 134 | } 135 | 136 | /** 137 | * Add messages to a gift card model. 138 | * Run the "createGiftCardModel" test before running this test. 139 | * POST http://xxx/hmspass/v1/giftcard/model/{modelId}/addMessage 140 | */ 141 | @Test 142 | public void addMessageToGiftCardModel() { 143 | System.out.println("addMessageToGiftCardModel begin."); 144 | 145 | // ID of the gift card model you want to update. 146 | String modelId = "GiftCardTestModel"; 147 | 148 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 149 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 150 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 151 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 152 | // messages at a time. 153 | 154 | // Read messages from a JSON file. 155 | String messagesStr = ConfigUtil.readFile("Messages.json"); 156 | 157 | // Add messages to the gift card model. 158 | String urlSegment = "/v1/giftcard/model/"; 159 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 160 | System.out.println("Updated gift card model: " + JSONObject.toJSONString(responseModel)); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/eventticket/EventTicketModelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.eventticket; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Event ticket model tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class EventTicketModelTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Create a new event ticket model. 39 | * Each event ticket model indicates a style of event ticket passes. 40 | * POST http://XXX/hmspass/v1/eventticket/model 41 | */ 42 | @Test 43 | public void createEventTicketModel() { 44 | System.out.println("createEventTicketModel begin."); 45 | 46 | // Read an event ticket model from a JSON file. 47 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("EventTicketModel.json")); 48 | 49 | // Validate parameters. 50 | HwWalletObjectUtil.validateModel(model); 51 | 52 | // Post the new event ticket model to HMS wallet server. 53 | String urlSegment = "/v1/eventticket/model"; 54 | JSONObject responseModel = serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(model)); 55 | System.out.println("Posted event ticket model: " + JSONObject.toJSONString(responseModel)); 56 | } 57 | 58 | /** 59 | * Get an event ticket model by its model ID. 60 | * Run the "createEventTicketModel" test before running this test. 61 | * GET http://xxx/hmspass/v1/eventticket/model/{modelId} 62 | */ 63 | @Test 64 | public void getEventTicketModel() { 65 | System.out.println("getEventTicketModel begin."); 66 | 67 | // ID of the event ticket model you want to get. 68 | String modelId = "EventTicketTestModel"; 69 | 70 | // Get the event ticket model. 71 | String urlSegment = "/v1/eventticket/model/"; 72 | JSONObject responseModel = serverApiService.getHwWalletObjectById(urlSegment, modelId); 73 | System.out.println("Corresponding event ticket model: " + JSONObject.toJSONString(responseModel)); 74 | } 75 | 76 | /** 77 | * Get event ticket models belonging to a specific appId. 78 | * Run the "createEventTicketModel" test before running this test. 79 | * GET http://xxx/hmspass/v1/eventticket/model?session=XXX&pageSize=XXX 80 | */ 81 | @Test 82 | public void getEventTicketModelList() { 83 | System.out.println("getEventTicketModelList begin."); 84 | 85 | // Get a list of event ticket models. 86 | String urlSegment = "/v1/eventticket/model"; 87 | 88 | JSONArray models = serverApiService.getModels(urlSegment, 5); 89 | System.out.println("Total models count: " + models.size()); 90 | System.out.println("Models list: " + models.toJSONString()); 91 | } 92 | 93 | /** 94 | * Overwrite an event ticket model. 95 | * Run the "createEventTicketModel" test before running this test. 96 | * PUT http://xxx/hmspass/v1/eventticket/model/{modelId} 97 | */ 98 | @Test 99 | public void fullUpdateEventTicketModel() { 100 | System.out.println("fullUpdateEventTicketModel begin."); 101 | 102 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding model. 103 | JSONObject model = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateEventTicketModel.json")); 104 | 105 | // Validate parameters. 106 | HwWalletObjectUtil.validateModel(model); 107 | 108 | // Update the event ticket model. 109 | String urlSegment = "/v1/eventticket/model/"; 110 | JSONObject responseModel = serverApiService.fullUpdateHwWalletObject(urlSegment, 111 | model.getString("passStyleIdentifier"), JSONObject.toJSONString(model)); 112 | System.out.println("Updated event ticket model: " + JSONObject.toJSONString(responseModel)); 113 | } 114 | 115 | /** 116 | * Update an event ticket model. 117 | * Run the "createEventTicketModel" test before running this test. 118 | * PATCH http://xxx/hmspass/v1/eventticket/model/{modelId} 119 | */ 120 | @Test 121 | public void partialUpdateEventTicketModel() { 122 | System.out.println("partialUpdateEventTicketModel begin."); 123 | 124 | // ID of the event ticket model you want to update. 125 | String modelId = "EventTicketTestModel"; 126 | 127 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding model. 128 | String modelStr = ConfigUtil.readFile("PartialUpdateEventTicketModel.json"); 129 | 130 | // Update the event ticket model. 131 | String urlSegment = "/v1/eventticket/model/"; 132 | JSONObject responseModel = serverApiService.partialUpdateHwWalletObject(urlSegment, modelId, modelStr); 133 | System.out.println("Updated event ticket model: " + JSONObject.toJSONString(responseModel)); 134 | } 135 | 136 | /** 137 | * Add messages to an event ticket model. 138 | * Run the "createEventTicketModel" test before running this test. 139 | * POST http://xxx/hmspass/v1/eventticket/model/{modelId}/addMessage 140 | */ 141 | @Test 142 | public void addMessageToEventTicketModel() { 143 | System.out.println("addMessageToEventTicketModel begin."); 144 | 145 | // ID of the event ticket model you want to update. 146 | String modelId = "EventTicketTestModel"; 147 | 148 | // Create a list of messages you want to add to a model. Each message contains key, value, and label. 149 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 150 | // a new message with the same key. One model contains at most 10 messages. If a model already have 10 messages 151 | // and you keep adding new messages, the oldest messages will be removed. You should not add more than 10 152 | // messages at a time. 153 | 154 | // Read messages from a JSON file. 155 | String messagesStr = ConfigUtil.readFile("Messages.json"); 156 | 157 | // Add messages to the event ticket model. 158 | String urlSegment = "/v1/eventticket/model/"; 159 | JSONObject responseModel = serverApiService.addMessageToHwWalletObject(urlSegment, modelId, messagesStr); 160 | System.out.println("Updated event ticket model: " + JSONObject.toJSONString(responseModel)); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/offer/OfferInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.offer; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Offer instance tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class OfferInstanceTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Add an offer instance to HMS wallet server. 39 | * Run the "createOfferModel" test before running this test. 40 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 41 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 42 | * POST http://XXX/hmspass/v1/offer/instance 43 | */ 44 | @Test 45 | public void addOfferInstance() { 46 | System.out.println("addOfferInstance begin."); 47 | 48 | // Read an offer instance from a JSON file. 49 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("OfferInstance.json")); 50 | 51 | // Validate parameters. 52 | HwWalletObjectUtil.validateInstance(instance); 53 | 54 | // Post the new offer instance to HMS wallet server. 55 | String urlSegment = "/v1/offer/instance"; 56 | JSONObject responseInstance = 57 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 58 | System.out.println("Posted offer instance: " + JSONObject.toJSONString(responseInstance)); 59 | } 60 | 61 | /** 62 | * Get an offer instance by its instance ID. 63 | * Run the "createOfferInstance" test before running this test. 64 | * GET http://xxx/hmspass/v1/offer/instance/{instanceId} 65 | */ 66 | @Test 67 | public void getOfferInstance() { 68 | System.out.println("getOfferInstance begin."); 69 | 70 | // ID of the offer instance you want to get. 71 | String instanceId = "OfferPass50001"; 72 | 73 | // Get the offer instance. 74 | String urlSegment = "/v1/offer/instance/"; 75 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 76 | System.out.println("Corresponding offer instance: " + JSONObject.toJSONString(responseInstance)); 77 | } 78 | 79 | /** 80 | * Get offer instance belonging to a specific offer model. 81 | * Run the "createOfferInstance" test before running this test. 82 | * GET http://xxx/hmspass/v1/offer/instance?modelId=XXX&session=XXX&pageSize=XXX 83 | */ 84 | @Test 85 | public void getOfferInstanceList() { 86 | System.out.println("getOfferInstanceList begin."); 87 | 88 | // Model ID of offer instances you want to get. 89 | String modelId = "OfferTestModel"; 90 | 91 | // Get a list of offer instances. 92 | String urlSegment = "/v1/offer/instance"; 93 | 94 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 95 | System.out.println("Total instances count: " + instances.size()); 96 | System.out.println("Instances list: " + instances.toJSONString()); 97 | } 98 | 99 | /** 100 | * Overwrite an offer instance. 101 | * Run the "createOfferInstance" test before running this test. 102 | * PUT http://xxx/hmspass/v1/offer/instance/{instanceId} 103 | */ 104 | @Test 105 | public void fullUpdateOfferInstance() { 106 | System.out.println("fullUpdateOfferInstance begin."); 107 | 108 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 109 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateOfferInstance.json")); 110 | 111 | // Validate parameters. 112 | HwWalletObjectUtil.validateInstance(instance); 113 | 114 | // Update the offer instance. 115 | String urlSegment = "/v1/offer/instance/"; 116 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 117 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 118 | System.out.println("Updated offer instance: " + JSONObject.toJSONString(responseInstance)); 119 | } 120 | 121 | /** 122 | * Update an offer instance. 123 | * Run the "createOfferInstance" test before running this test. 124 | * PATCH http://xxx/hmspass/v1/offer/instance/{instanceId} 125 | */ 126 | @Test 127 | public void partialUpdateOfferInstance() { 128 | System.out.println("partialUpdateOfferInstance begin."); 129 | 130 | // ID of the offer instance you want to update. 131 | String instanceId = "OfferPass50001"; 132 | 133 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 134 | String instanceStr = ConfigUtil.readFile("PartialUpdateOfferInstance.json"); 135 | 136 | // Update the offer instance. 137 | String urlSegment = "/v1/offer/instance/"; 138 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 139 | System.out.println("Updated offer instance: " + JSONObject.toJSONString(responseInstance)); 140 | } 141 | 142 | /** 143 | * Add messages to an offer instance. 144 | * Run the "createOfferInstance" test before running this test. 145 | * POST http://xxx/hmspass/v1/offer/instance/{instanceId}/addMessage 146 | */ 147 | @Test 148 | public void addMessageToOfferInstance() { 149 | System.out.println("addMessageToOfferInstance begin."); 150 | 151 | // ID of the offer instance you want to update. 152 | String instanceId = "OfferPass50001"; 153 | 154 | // Create a list of messages you want to add to an instance. Each message contains key, value, and label. 155 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 156 | // a new message with the same key. One instance contains at most 10 messages. If an instance already have 10 157 | // messages and you keep adding new messages, the oldest messages will be removed. You should not add more than 158 | // 10 messages at a time. 159 | 160 | // Read messages from a JSON file. 161 | String messagesStr = ConfigUtil.readFile("Messages.json"); 162 | 163 | // Add messages to the offer instance. 164 | String urlSegment = "/v1/offer/instance/"; 165 | JSONObject responseInstance = serverApiService.addMessageToHwWalletObject(urlSegment, instanceId, messagesStr); 166 | System.out.println("Updated offer instance: " + JSONObject.toJSONString(responseInstance)); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/flight/FlightInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.flight; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Flight instance tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class FlightInstanceTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Add a flight instance to HMS wallet server. 39 | * Run the "createFlightModel" test before running this test. 40 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 41 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 42 | * POST http://XXX/hmspass/v1/flight/instance 43 | */ 44 | @Test 45 | public void addFlightInstance() { 46 | System.out.println("addFlightInstance begin."); 47 | 48 | // Read a flight instance from a JSON file. 49 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FlightInstance.json")); 50 | 51 | // Validate parameters. 52 | HwWalletObjectUtil.validateInstance(instance); 53 | 54 | // Post the new flight instance to HMS wallet server. 55 | String urlSegment = "/v1/flight/instance"; 56 | JSONObject responseInstance = 57 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 58 | System.out.println("Posted flight instance: " + JSONObject.toJSONString(responseInstance)); 59 | } 60 | 61 | /** 62 | * Get a flight instance by its instance ID. 63 | * Run the "createFlightInstance" test before running this test. 64 | * GET http://xxx/hmspass/v1/flight/instance/{instanceId} 65 | */ 66 | @Test 67 | public void getFlightInstance() { 68 | System.out.println("getFlightInstance begin."); 69 | 70 | // ID of the flight instance you want to get. 71 | String instanceId = "FlightPass20001"; 72 | 73 | // Get the flight instance. 74 | String urlSegment = "/v1/flight/instance/"; 75 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 76 | System.out.println("Corresponding flight instance: " + JSONObject.toJSONString(responseInstance)); 77 | } 78 | 79 | /** 80 | * Get flight instance belonging to a specific flight model. 81 | * Run the "createFlightInstance" test before running this test. 82 | * GET http://xxx/hmspass/v1/flight/instance?modelId=XXX&session=XXX&pageSize=XXX 83 | */ 84 | @Test 85 | public void getFlightInstanceList() { 86 | System.out.println("getFlightInstanceList begin."); 87 | 88 | // Model ID of flight instances you want to get. 89 | String modelId = "FlightTestModel"; 90 | 91 | // Get a list of flight instances. 92 | String urlSegment = "/v1/flight/instance"; 93 | 94 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 95 | System.out.println("Total instances count: " + instances.size()); 96 | System.out.println("Instances list: " + instances.toJSONString()); 97 | } 98 | 99 | /** 100 | * Overwrite a flight instance. 101 | * Run the "createFlightInstance" test before running this test. 102 | * PUT http://xxx/hmspass/v1/flight/instance/{instanceId} 103 | */ 104 | @Test 105 | public void fullUpdateFlightInstance() { 106 | System.out.println("fullUpdateFlightInstance begin."); 107 | 108 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 109 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateFlightInstance.json")); 110 | 111 | // Validate parameters. 112 | HwWalletObjectUtil.validateInstance(instance); 113 | 114 | // Update the flight instance. 115 | String urlSegment = "/v1/flight/instance/"; 116 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 117 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 118 | System.out.println("Updated flight instance: " + JSONObject.toJSONString(responseInstance)); 119 | } 120 | 121 | /** 122 | * Update a flight instance. 123 | * Run the "createFlightInstance" test before running this test. 124 | * PATCH http://xxx/hmspass/v1/flight/instance/{instanceId} 125 | */ 126 | @Test 127 | public void partialUpdateFlightInstance() { 128 | System.out.println("partialUpdateFlightInstance begin."); 129 | 130 | // ID of the flight instance you want to update. 131 | String instanceId = "FlightPass20001"; 132 | 133 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 134 | String instanceStr = ConfigUtil.readFile("PartialUpdateFlightInstance.json"); 135 | 136 | // Update the flight instance. 137 | String urlSegment = "/v1/flight/instance/"; 138 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 139 | System.out.println("Updated flight instance: " + JSONObject.toJSONString(responseInstance)); 140 | } 141 | 142 | /** 143 | * Add messages to a flight instance. 144 | * Run the "createFlightInstance" test before running this test. 145 | * POST http://xxx/hmspass/v1/flight/instance/{instanceId}/addMessage 146 | */ 147 | @Test 148 | public void addMessageToFlightInstance() { 149 | System.out.println("addMessageToFlightInstance begin."); 150 | 151 | // ID of the flight instance you want to update. 152 | String instanceId = "FlightPass20001"; 153 | 154 | // Create a list of messages you want to add to an instance. Each message contains key, value, and label. 155 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 156 | // a new message with the same key. One instance contains at most 10 messages. If an instance already have 10 157 | // messages and you keep adding new messages, the oldest messages will be removed. You should not add more than 158 | // 10 messages at a time. 159 | 160 | // Read messages from a JSON file. 161 | String messagesStr = ConfigUtil.readFile("Messages.json"); 162 | 163 | // Add messages to the flight instance. 164 | String urlSegment = "/v1/flight/instance/"; 165 | JSONObject responseInstance = serverApiService.addMessageToHwWalletObject(urlSegment, instanceId, messagesStr); 166 | System.out.println("Updated flight instance: " + JSONObject.toJSONString(responseInstance)); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/transit/TransitInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.transit; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Transit instance tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class TransitInstanceTest { 35 | private ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Add a transit instance to HMS wallet server. 39 | * Run the "createTransitModel" test before running this test. 40 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 41 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 42 | * POST http://XXX/hmspass/v1/transit/instance 43 | */ 44 | @Test 45 | public void addTransitInstance() { 46 | System.out.println("addTransitInstance begin."); 47 | 48 | // Read a transit instance from a JSON file. 49 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("TransitInstance.json")); 50 | 51 | // Validate parameters. 52 | HwWalletObjectUtil.validateInstance(instance); 53 | 54 | // Post the new transit instance to HMS wallet server. 55 | String urlSegment = "/v1/transit/instance"; 56 | JSONObject responseInstance = 57 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 58 | System.out.println("Posted transit instance: " + JSONObject.toJSONString(responseInstance)); 59 | } 60 | 61 | /** 62 | * Get a transit instance by its instance ID. 63 | * Run the "createTransitInstance" test before running this test. 64 | * GET http://xxx/hmspass/v1/transit/instance/{instanceId} 65 | */ 66 | @Test 67 | public void getTransitInstance() { 68 | System.out.println("getTransitInstance begin."); 69 | 70 | // ID of the transit instance you want to get. 71 | String instanceId = "TransitPass60001"; 72 | 73 | // Get the transit instance. 74 | String urlSegment = "/v1/transit/instance/"; 75 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 76 | System.out.println("Corresponding transit instance: " + JSONObject.toJSONString(responseInstance)); 77 | } 78 | 79 | /** 80 | * Get transit instance belonging to a specific transit model. 81 | * Run the "createTransitInstance" test before running this test. 82 | * GET http://xxx/hmspass/v1/transit/instance?modelId=XXX&session=XXX&pageSize=XXX 83 | */ 84 | @Test 85 | public void getTransitInstanceList() { 86 | System.out.println("getTransitInstanceList begin."); 87 | 88 | // Model ID of offer instances you want to get. 89 | String modelId = "TransitTestModel"; 90 | 91 | // Get a list of transit instances. 92 | String urlSegment = "/v1/transit/instance"; 93 | 94 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 95 | System.out.println("Total instances count: " + instances.size()); 96 | System.out.println("Instances list: " + instances.toJSONString()); 97 | } 98 | 99 | /** 100 | * Overwrite a transit instance. 101 | * Run the "createTransitInstance" test before running this test. 102 | * PUT http://xxx/hmspass/v1/transit/instance/{instanceId} 103 | */ 104 | @Test 105 | public void fullUpdateTransitInstance() { 106 | System.out.println("fullUpdateTransitInstance begin."); 107 | 108 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 109 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateTransitInstance.json")); 110 | 111 | // Validate parameters. 112 | HwWalletObjectUtil.validateInstance(instance); 113 | 114 | // Update the transit instance. 115 | String urlSegment = "/v1/transit/instance/"; 116 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 117 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 118 | System.out.println("Updated transit instance: " + JSONObject.toJSONString(responseInstance)); 119 | } 120 | 121 | /** 122 | * Update a transit instance. 123 | * Run the "createTransitInstance" test before running this test. 124 | * PATCH http://xxx/hmspass/v1/transit/instance/{instanceId} 125 | */ 126 | @Test 127 | public void partialUpdateTransitInstance() { 128 | System.out.println("partialUpdateTransitInstance begin."); 129 | 130 | // ID of the transit instance to you want to update. 131 | String instanceId = "TransitPass60001"; 132 | 133 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 134 | String instanceStr = ConfigUtil.readFile("PartialUpdateTransitInstance.json"); 135 | 136 | // Update the transit instance. 137 | String urlSegment = "/v1/transit/instance/"; 138 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 139 | System.out.println("Updated transit instance: " + JSONObject.toJSONString(responseInstance)); 140 | } 141 | 142 | /** 143 | * Add messages to a transit instance. 144 | * Run the "createTransitInstance" test before running this test. 145 | * POST http://xxx/hmspass/v1/transit/instance/{instanceId}/addMessage 146 | */ 147 | @Test 148 | public void addMessageToTransitInstance() { 149 | System.out.println("addMessageToTransitInstance begin."); 150 | 151 | // ID of the transit instance to you want to update. 152 | String instanceId = "TransitPass60001"; 153 | 154 | // Create a list of messages you want to add to an instance. Each message contains key, value, and label. 155 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 156 | // a new message with the same key. One instance contains at most 10 messages. If an instance already have 10 157 | // messages and you keep adding new messages, the oldest messages will be removed. You should not add more than 158 | // 10 messages at a time. 159 | 160 | // Read messages from a JSON file. 161 | String messagesStr = ConfigUtil.readFile("Messages.json"); 162 | 163 | // Add messages to the transit instance. 164 | String urlSegment = "/v1/transit/instance/"; 165 | JSONObject responseInstance = serverApiService.addMessageToHwWalletObject(urlSegment, instanceId, messagesStr); 166 | System.out.println("Updated transit instance: " + JSONObject.toJSONString(responseInstance)); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/giftcard/GiftCardInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.giftcard; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Gift card instance tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class GiftCardInstanceTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Add a gift card instance to HMS wallet server. 39 | * Run the "createGiftCardModel" test before running this test. 40 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 41 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 42 | * POST http://XXX/hmspass/v1/giftcard/instance 43 | */ 44 | @Test 45 | public void addGiftCardInstance() { 46 | System.out.println("addGiftCardInstance begin."); 47 | 48 | // Read a gift card instance from a JSON file. 49 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("GiftCardInstance.json")); 50 | 51 | // Validate parameters. 52 | HwWalletObjectUtil.validateInstance(instance); 53 | 54 | // Post the new gift card instance to HMS wallet server. 55 | String urlSegment = "/v1/giftcard/instance"; 56 | JSONObject responseInstance = 57 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 58 | System.out.println("Posted gift card instance: " + JSONObject.toJSONString(responseInstance)); 59 | } 60 | 61 | /** 62 | * Get a gift card instance by its instance ID. 63 | * Run the "createGiftCardInstance" test before running this test. 64 | * GET http://xxx/hmspass/v1/giftcard/instance/{instanceId} 65 | */ 66 | @Test 67 | public void getGiftCardInstance() { 68 | System.out.println("getGiftCardInstance begin."); 69 | 70 | // ID of the gift card instance you want to get. 71 | String instanceId = "GiftCardPass30001"; 72 | 73 | // Get the gift card instance. 74 | String urlSegment = "/v1/giftcard/instance/"; 75 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 76 | System.out.println("Corresponding gift card instance: " + JSONObject.toJSONString(responseInstance)); 77 | } 78 | 79 | /** 80 | * Get gift card instance belonging to a specific gift card model. 81 | * Run the "createGiftCardInstance" test before running this test. 82 | * GET http://xxx/hmspass/v1/giftcard/instance?modelId=XXX&session=XXX&pageSize=XXX 83 | */ 84 | @Test 85 | public void getGiftCardInstanceList() { 86 | System.out.println("getGiftCardInstanceList begin."); 87 | 88 | // Model ID of gift card instances you want to get. 89 | String modelId = "GiftCardTestModel"; 90 | 91 | // Get a list of gift card instances. 92 | String urlSegment = "/v1/giftcard/instance"; 93 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 94 | System.out.println("Total instances count: " + instances.size()); 95 | System.out.println("Instances list: " + instances.toJSONString()); 96 | } 97 | 98 | /** 99 | * Overwrite a gift card instance. 100 | * Run the "createGiftCardInstance" test before running this test. 101 | * PUT http://xxx/hmspass/v1/giftcard/instance/{instanceId} 102 | */ 103 | @Test 104 | public void fullUpdateGiftCardInstance() { 105 | System.out.println("fullUpdateGiftCardInstance begin."); 106 | 107 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 108 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateGiftCardInstance.json")); 109 | 110 | // Validate parameters. 111 | HwWalletObjectUtil.validateInstance(instance); 112 | 113 | // Update the gift card instance. 114 | String urlSegment = "/v1/giftcard/instance/"; 115 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 116 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 117 | System.out.println("Updated gift card instance: " + JSONObject.toJSONString(responseInstance)); 118 | } 119 | 120 | /** 121 | * Update a gift card instance. 122 | * Run the "createGiftCardInstance" test before running this test. 123 | * PATCH http://xxx/hmspass/v1/giftcard/instance/{instanceId} 124 | */ 125 | @Test 126 | public void partialUpdateGiftCardInstance() { 127 | System.out.println("partialUpdateGiftCardInstance begin."); 128 | 129 | // ID of the gift card instance you want to update. 130 | String instanceId = "GiftCardPass30001"; 131 | 132 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 133 | String instanceStr = ConfigUtil.readFile("PartialUpdateGiftCardInstance.json"); 134 | 135 | // Update the gift card instance. 136 | String urlSegment = "/v1/giftcard/instance/"; 137 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 138 | System.out.println("Updated gift card instance: " + JSONObject.toJSONString(responseInstance)); 139 | } 140 | 141 | /** 142 | * Add messages to a gift card instance. 143 | * Run the "createGiftCardInstance" test before running this test. 144 | * POST http://xxx/hmspass/v1/giftcard/instance/{instanceId}/addMessage 145 | */ 146 | @Test 147 | public void addMessageToGiftCardInstance() { 148 | System.out.println("addMessageToGiftCardInstance begin."); 149 | 150 | // ID of the gift card instance you want to update. 151 | String instanceId = "GiftCardPass30001"; 152 | 153 | // Create a list of messages you want to add to an instance. Each message contains key, value, and label. 154 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 155 | // a new message with the same key. One instance contains at most 10 messages. If an instance already have 10 156 | // messages and you keep adding new messages, the oldest messages will be removed. You should not add more than 157 | // 10 messages at a time. 158 | 159 | // Read messages from a JSON file. 160 | String messagesStr = ConfigUtil.readFile("Messages.json"); 161 | 162 | // Add messages to the gift card instance. 163 | String urlSegment = "/v1/giftcard/instance/"; 164 | JSONObject responseInstance = serverApiService.addMessageToHwWalletObject(urlSegment, instanceId, messagesStr); 165 | System.out.println("Updated gift card instance: " + JSONObject.toJSONString(responseInstance)); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/test/java/com/huawei/wallet/hms/eventticket/EventTicketInstanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.hms.eventticket; 18 | 19 | import com.huawei.wallet.hms.ServerApiService; 20 | import com.huawei.wallet.hms.ServerApiServiceImpl; 21 | import com.huawei.wallet.util.ConfigUtil; 22 | import com.huawei.wallet.util.HwWalletObjectUtil; 23 | 24 | import com.alibaba.fastjson.JSONArray; 25 | import com.alibaba.fastjson.JSONObject; 26 | 27 | import org.junit.Test; 28 | 29 | /** 30 | * Event ticket instance tests. 31 | * 32 | * @since 2019-12-12 33 | */ 34 | public class EventTicketInstanceTest { 35 | private final ServerApiService serverApiService = new ServerApiServiceImpl(); 36 | 37 | /** 38 | * Add an event ticket instance to HMS wallet server. 39 | * Run the "createEventTicketModel" test before running this test. 40 | * After using this API, you will use a thin JWE to bind this instance to a user. Or you can add an instance by 41 | * sending a JWE with complete instance information, without using this API. See JWE example tests. 42 | * POST http://XXX/hmspass/v1/eventticket/instance 43 | */ 44 | @Test 45 | public void addEventTicketInstance() { 46 | System.out.println("addEventTicketInstance begin."); 47 | 48 | // Read an event ticket instance from a JSON file. 49 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("EventTicketInstance.json")); 50 | 51 | // Validate parameters. 52 | HwWalletObjectUtil.validateInstance(instance); 53 | 54 | // Post the new event ticket instance to HMS wallet server. 55 | String urlSegment = "/v1/eventticket/instance"; 56 | JSONObject responseInstance = 57 | serverApiService.postToWalletServer(urlSegment, JSONObject.toJSONString(instance)); 58 | System.out.println("Posted event ticket instance: " + JSONObject.toJSONString(responseInstance)); 59 | } 60 | 61 | /** 62 | * Get an event ticket instance by its instance ID. 63 | * Run the "createEventTicketInstance" test before running this test. 64 | * GET http://xxx/hmspass/v1/eventticket/instance/{instanceId} 65 | */ 66 | @Test 67 | public void getEventTicketInstance() { 68 | System.out.println("getEventTicketInstance begin."); 69 | 70 | // ID of the event ticket instance you want to get. 71 | String instanceId = "EventTicketPass10001"; 72 | 73 | // Get the event ticket instance. 74 | String urlSegment = "/v1/eventticket/instance/"; 75 | JSONObject responseInstance = serverApiService.getHwWalletObjectById(urlSegment, instanceId); 76 | System.out.println("Corresponding event ticket instance: " + JSONObject.toJSONString(responseInstance)); 77 | } 78 | 79 | /** 80 | * Get event ticket instances belonging to a specific event ticket model. 81 | * Run the "createEventTicketInstance" test before running this test. 82 | * GET http://xxx/hmspass/v1/eventticket/instance?modelId=XXX&session=XXX&pageSize=XXX 83 | */ 84 | @Test 85 | public void getEventTicketInstanceList() { 86 | System.out.println("getEventTicketInstanceList begin."); 87 | 88 | // Model ID of event ticket instances you want to get. 89 | String modelId = "EventTicketTestModel"; 90 | 91 | // Get a list of the event ticket instances. 92 | String urlSegment = "/v1/eventticket/instance"; 93 | 94 | JSONArray instances = serverApiService.getInstances(urlSegment, modelId, 5); 95 | System.out.println("Total instances count: " + instances.size()); 96 | System.out.println("Instances list: " + instances.toJSONString()); 97 | } 98 | 99 | /** 100 | * Overwrite an event ticket instance. 101 | * Run the "createEventTicketInstance" test before running this test. 102 | * PUT http://xxx/hmspass/v1/eventticket/instance/{instanceId} 103 | */ 104 | @Test 105 | public void fullUpdateEventTicketInstance() { 106 | System.out.println("fullUpdateEventTicketInstance begin."); 107 | 108 | // Read a HwWalletObject from a JSON file. This HwWalletObject will overwrite the corresponding instance. 109 | JSONObject instance = JSONObject.parseObject(ConfigUtil.readFile("FullUpdateEventTicketInstance.json")); 110 | 111 | // Validate parameters. 112 | HwWalletObjectUtil.validateInstance(instance); 113 | 114 | // Update the event ticket instance. 115 | String urlSegment = "/v1/eventticket/instance/"; 116 | JSONObject responseInstance = serverApiService.fullUpdateHwWalletObject(urlSegment, 117 | instance.getString("serialNumber"), JSONObject.toJSONString(instance)); 118 | System.out.println("Updated event ticket instance: " + JSONObject.toJSONString(responseInstance)); 119 | } 120 | 121 | /** 122 | * Update an event ticket instance. 123 | * Run the "createEventTicketInstance" test before running this test. 124 | * PATCH http://xxx/hmspass/v1/eventticket/instance/{instanceId} 125 | */ 126 | @Test 127 | public void partialUpdateEventTicketInstance() { 128 | System.out.println("partialUpdateEventTicketInstance begin."); 129 | 130 | // ID of the event ticket instance you want to update. 131 | String instanceId = "EventTicketPass10001"; 132 | 133 | // Read a HwWalletObject from a JSON file. This HwWalletObject will merge with the corresponding instance. 134 | String instanceStr = ConfigUtil.readFile("PartialUpdateEventTicketInstance.json"); 135 | 136 | // Update the event ticket instance. 137 | String urlSegment = "/v1/eventticket/instance/"; 138 | JSONObject responseInstance = serverApiService.partialUpdateHwWalletObject(urlSegment, instanceId, instanceStr); 139 | System.out.println("Updated event ticket instance: " + JSONObject.toJSONString(responseInstance)); 140 | } 141 | 142 | /** 143 | * Add messages to an event ticket instance. 144 | * Run the "createEventTicketInstance" test before running this test. 145 | * POST http://xxx/hmspass/v1/eventticket/instance/{instanceId}/addMessage 146 | */ 147 | @Test 148 | public void addMessageToEventTicketInstance() { 149 | System.out.println("addMessageToEventTicketInstance begin."); 150 | 151 | // ID of the event ticket instance you want to update. 152 | String instanceId = "EventTicketPass10001"; 153 | 154 | // Create a list of messages you want to add to an instance. Each message contains key, value, and label. 155 | // The list should not contain multiple messages with the same key. You can update an existing message by adding 156 | // a new message with the same key. One instance contains at most 10 messages. If an instance already have 10 157 | // messages and you keep adding new messages, the oldest messages will be removed. You should not add more than 158 | // 10 messages at a time. 159 | 160 | // Read messages from a JSON file. 161 | String messagesStr = ConfigUtil.readFile("Messages.json"); 162 | 163 | // Add messages to the event ticket instance. 164 | String urlSegment = "/v1/eventticket/instance/"; 165 | JSONObject responseInstance = serverApiService.addMessageToHwWalletObject(urlSegment, instanceId, messagesStr); 166 | System.out.println("Updated event ticket instance: " + JSONObject.toJSONString(responseInstance)); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # 华为钱包服务服务端示例代码 2 | ### 目录 3 | * [安装](#安装) 4 | * [环境要求](#环境要求) 5 | * [申请华为钱包服务](#申请华为钱包服务) 6 | * [配置参数](#配置参数) 7 | * [配置模板和实例](#配置模板和实例) 8 | * [编译Maven工程](#编译Maven工程) 9 | * [示例方法](#示例方法) 10 | 1. [卡券模板示例方法](#卡券模板示例方法) 11 | 1. [卡券实例示例方法](#卡券实例示例方法) 12 | 1. [生成JWE](#生成JWE) 13 | 1. [验签](#验签) 14 | * [技术支持](#技术支持) 15 | * [授权许可](#授权许可) 16 | 17 | 18 | ## 简介 19 | 华为钱包服务(HUAWEI Wallet Kit)服务端示例代码介绍了如何调用华为钱包服务器接口。华为钱包服务器提供多个REST接口,支持六类卡券(会员卡、优惠券、礼品卡、登机牌、交通车票和活动门票)。您可以调用这些接口进行卡券添加、查询、更新等操作。 20 | 在使用此示例代码前,您需在华为开发者联盟上创建一个开发者账号,并在[AppGallery Connect](https://developer.huawei.com/consumer/cn/service/josp/agc/index.html)上创建一个应用。该应用仅表明您要申请使用华为钱包服务,并不一定是手机上的真实应用,因此即使您不打算开发端侧应用,也需要进行此操作。详情请参阅[注册账号](https://developer.huawei.com/consumer/cn/doc/start/10104)和[创建应用](https://developer.huawei.com/consumer/cn/doc/distribution/app/agc-create_app)。 21 | 22 | ## 环境要求 23 | 示例代码的运行环境为Maven和Oracle Java(1.8.0.211及以上版本)。 24 | 25 | ## 申请华为钱包服务 26 | 参照[开通服务](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-enable_service) 申请华为钱包服务。
27 | 28 | 请注意在申请钱包服务的过程中需要创建一个服务号,该服务号即为passTypeIdentifier的值,后续将在配置示例代码中用到。
29 | 30 | 您在申请过程中还会创建一对RSA公私钥,请妥善保管。其中私钥用于后续对JWE进行签名 (详情请参阅 [生成JWE](#generate-jwe)). 公钥用于钱包服务器验签。
31 | 32 | 在设置完一类卡券的服务号之后,你就可以运行这个卡券对应的示例代码了。如果你想测试其他卡券,则需申请其他卡券的服务号。 33 | 34 | ## 配置参数 35 | 运行示例代码前,在”src\test\resources\release.config.properties”文件中配置如下参数:”gw.appid”, “gw.appid.secret”, “gw.tokenUrl”, “walletServerBaseUrl”, “servicePrivateKey”和“walletWebsiteBaseUrl”。 36 | 37 | #### 设置 "gw.appid" and "gw.appid.secret": 38 | "gw.appid"和"gw.appid.secret"为应用的"APP ID"和"SecretKey"。登录[AppGallery Connect](https://developer.huawei.com/consumer/cn/service/josp/agc/index.html),点击“我的应用”,选择目标应用,即可找到该应用的APP ID和SecretKey。 39 | 40 | #### 设置 "gw.tokenUrl" 41 | 将gw.tokenUrl设置为https://oauth-login.cloud.huawei.com/oauth2/v3/token,即获取REST接口认证token的地址。 42 | 43 | #### 设置 "walletServerBaseUrl": 44 | "walletServerBaseUrl" 为REST接口请求的公共部分,格式为https://{walletkit_server_url}/hmspass。其中{walletkit_server_url}需要根据您的账号所属国家/地区自行替换,如下表: 45 | | 国家/地区 | walletkit_server_url | 46 | |------------------ |------------------------------------- | 47 | | 中国大陆 | wallet-passentrust-drcn.cloud.huawei.com.cn | 48 | | 亚洲 | wallet-passentrust-dra.cloud.huawei.asia | 49 | | 欧洲 | wallet-passentrust-dre.cloud.huawei.eu | 50 | | 拉丁美洲 | wallet-passentrust-dra.cloud.huawei.lat | 51 | | 俄罗斯 | wallet-passentrust-drru.cloud.huawei.ru | 52 | 53 | #### 设置 "servicePrivateKety" 54 | 将"servicePrivateKey"设置为您在[申请华为钱包服务](#申请华为钱包服务)时生成的RSA私钥。您将用此参数对JWE进行签名。 55 | 56 | #### 设置 "walletWebsiteBaseUrl" 57 | "walletWebsiteBaseUrl" 是华为钱包H5服务器地址,格式为https://{walletkit_website_url}/walletkit/consumer/pass/save。其中{walletkit_server_url}需要根据您的账号所属国家/地区自行替换,如下表: 58 | | 国家/地区 | walletkit_website_url | 59 | |-------------------|------------------------------------ | 60 | | 中国大陆 | walletpass-drcn.cloud.huawei.com | 61 | | 亚洲 | walletpass-dra.cloud.huawei.com | 62 | | 欧洲 | walletpass-dre.cloud.huawei.com | 63 | | 拉丁美洲 | walletpass-dra.cloud.huawei.com | 64 | | 俄罗斯 | walletpass-drru.cloud.huawei.com | 65 | 66 | ## 卡券模板和实例 67 | 一个模板代表一种卡券。同一模板下的实例会共享某些参数。例如,一个登机牌模板含有出发和抵达时间等信息,而一个登机牌实例则含有某乘客的姓名、座位号、登机顺序等信息。每一个卡券实例都有一个对应的模板。因此,您需要先创建一个卡券模板,然后才能创建卡券并进行其他操作。
68 | 69 | 所有卡券模板和实例的数据类型均为HwWalletObject。详情请参阅[HwWalletObject Definition](https://developer.huawei.com/consumer/en/doc/development/HMSCore-References-V5/def-0000001050160319-V5) for more details.
70 | 71 | 在示例代码中,卡券模板和实例的入参均通过"src\test\resources\data"文件夹下的JSON文件传入。您可以自行修改JSON文件来生成您想要的卡券。
72 | 73 | 请把JSON文件中"passTypeIdentifier"的值设置为您在[AppGallery Connect](https://developer.huawei.com/consumer/cn/service/josp/agc/index.html)上设置的服务号。 74 | 75 | ## 编译Maven工程 76 | 设置完上述参数后,请将示例代码编译为Maven工程。将全部依赖部署完毕可能要花几分钟时间,具体取决于您的配置文件和网络状况。 77 | 78 | ## 示例方法 79 | ### 卡券模板示例方法 80 | #### 1. 创建一个卡券模板 81 | 华为钱包服务器提供REST接口用于创建卡券模板。例如,您可通过调用createLoyaltyModel添加会员卡模板到服务器数据库,具体请参阅[创建会员卡模板](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/create-model-0000001050158390-V5)。添加其他类型卡券方法类似。调用其他相关方法前须先创建卡券模板。 82 | 83 | #### 2. 查询单个卡券模板 84 | 华为钱包服务器提供REST接口用于根据模板ID查询卡券模板。例如,您可通过调用getLoyaltyModel查询会员卡模板,详情请参阅[单个查询会员卡模板](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/query-model-0000001050160345-V5)。查询其他类型卡券模板方法类似。 85 | 86 | #### 3. 查询卡券模板列表 87 | 如果您创建了多个同一卡券类型的模板(如金卡模板和钻石卡模板),您可通过调用相应接口查询模板列表。例如,可通过调用getLoyaltyModelList查询会员卡模板列表,详情请参阅[批量查询会员卡模板](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/list-model-0000001050158392-V5)。查询其他类型卡券模板列表方法类似。 88 | 89 | #### 4. 全量更新卡券模板 90 | 华为钱包服务器提供REST接口用于根据模板ID全量更新卡券模板。例如,可通过调用fullUpdateLoyaltyModel全量更新会员卡模板,详情请参阅[全量更新会员卡模板](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/overwrite-model-0000001050160347-V5)。全量更新其他类型卡券模板方法类似。 91 | 92 | #### 5. 局部更新卡券模板 93 | 华为钱包提供REST接口用于根据模板ID局部更新卡券模板。例如,可通过调用partialUpdateLoyaltyModel局部更新会员卡模板,详情请参阅[局部更新会员卡模板](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/update-model-0000001050158394-V5)。局部更新其他类型卡券模板方法类似。 94 | 95 | #### 6. 增加消息到卡券模板 96 | 华为钱包提供REST接口用于添加消息到卡券模板。例如,您可通过调用addMessageToLoyaltyModel添加消息到会员卡模板。详情请参阅会员卡模板增加message。添加消息到其他类型模板方法类似。卡券模板中messageList表示消息列表,最多支持十条消息。如果已添加的消息数量达到十条,继续添加将导致最早的消息被删除。 97 | 98 | ### 卡券实例示例方法 99 | #### 1. 新增一个卡券实例 100 | 华为钱包服务器提供REST接口用于新增卡券实例。例如,可通过调用createLoyaltyInstance新增会员卡实例到服务器数据库,详情请参阅[新增会员卡实例](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/add-instance-0000001050158396-V5)。新增其他类型卡券实例方法类似。创建实例前,您需先创建该实例所属的模板。 101 | 102 | #### 2. 查询卡券实例 103 | 华为钱包服务器提供REST接口用于根据实例ID查询卡券实例。例如,可通过调用getLoyaltyInstance查询会员卡实例,详情可参阅查询会员卡实例。查询其他类型卡券方法类似。 104 | 105 | #### 3. 全量更新卡券实例 106 | 华为钱包服务器提供REST接口用于根据实例ID全量更新卡券实例。例如,可通过调用fullUpdateLoyaltyInstance全量更新会员卡实例,详情请参阅[全量更新会员卡实例](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/overwrite-instance-0000001050160353-V5)。全量更新其他类型卡券实例方法类似。 107 | 108 | #### 4. 局部更新卡券实例 109 | 华为钱包服务器提供REST接口用于根据实例ID局部更新卡券实例。例如,可通过调用partialUpdateLoyaltyInstance局部更新会员卡实例,详情请参阅[局部更新会员卡实例](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/update-instance-0000001050158400-V5)。局部更新其他类型卡券实例方法类似。 110 | 111 | #### 5. 添加消息到卡券实例 112 | 华为钱包服务器提供REST接口用于添加消息到卡券实例。例如,可通过调用addMessageToLoyaltyInstance增加消息到某个会员卡实例,详情请参阅[会员卡实例增加message](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/instance-add-message-0000001050160355-V5)。增加消息到其他类型卡券实例方法类似。messageList是卡券实例的一个属性,最多支持十条消息。如果已添加的消息达到十条,继续添加将导致最早的消息被删除。 113 | 114 | #### 6. 关联/去关联会员卡实例的优惠券实例 115 | 本接口仅适用于会员卡实例。可通过调用updateLinkedOffersToLoyaltyInstance为一个会员卡实例新增或删除关联的优惠券实例。详情请参阅[关联/去关联优惠券实例](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/link-offer-instance-0000001050158402-V5)。在调用此接口用于关联优惠券前,需确保想要关联的优惠券实例存在于钱包服务器中,否则客户端无法展示该优惠券。您要关联的优惠券可以属于其他应用。 116 | 117 | ### 生成JWE 118 | 您需要生成JWE字符串并发送到[华为钱包H5服务器](#set-"walletwebsitebaseurl"),从而将卡券与某个华为钱包用户绑定。
119 | 您可通过以下两种方式生成JWE。第一种方法: 生成包含完整卡券实例信息的JWE并发送到华为钱包H5服务器。此时您无需调用[添加卡券实例](https://github.com/HMS-Core/hms-wallet-severdemo#add-a-pass-instance)接口。第二种方法:调用接口[添加卡券实例](https://github.com/HMS-Core/hms-wallet-severdemo#add-a-pass-instance)到钱包服务器,生成仅含卡券实例ID信息的瘦JWE并发送到华为钱包H5服务器,从而将卡券实例与某个用户绑定。
120 | 本示例代码提供生成JWE和瘦JWE的方法供您参考。更多信息请参阅[网页集成“添加到华为钱包”按钮领取卡券](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides-V5/guide-webpage-0000001050042334-V5)中“生成JWE并发送到华为服务器”和“生成瘦JWE并发送到华为服务器”部分。 121 | 122 | ### 验签 123 | 若您在[申请华为钱包服务](#apply-for-wallet-kit-service)过程中设置了回调地址或NFC回调地址,您可接收到华为钱包服务器发送的通知请求。此类请求的请求头携带了签名,您需用华为提供的固定公钥验证该签名。您可参考示例代码中的verifySignature进行验签。详情请参阅[回调接口公共定义](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/public-0000001050158472-V5)。 124 | 125 | ## 技术支持 126 | 如果您对HMS Core还处于评估阶段,可在[Reddit社区](https://www.reddit.com/r/HuaweiDevelopers/)获取关于HMS Core的最新讯息,并与其他开发者交流见解。 127 | 128 | 如果您对使用HMS示例代码有疑问,请尝试: 129 | - 开发过程遇到问题上[Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services),在`huawei-mobile-services`标签下提问,有华为研发专家在线一对一解决您的问题。 130 | - 到[华为开发者论坛](https://developer.huawei.com/consumer/cn/forum/blockdisplay?fid=18) HMS Core板块与其他开发者进行交流。 131 | 132 | 如果您在尝试示例代码中遇到问题,请向仓库提交[issue](https://github.com/HMS-Core/hms-wallet-severdemo/issues),也欢迎您提交[Pull Request](https://github.com/HMS-Core/hms-wallet-severdemo/pulls)。 133 | 134 | ## 授权许可 135 | 华为钱包服务服务端示例代码经过[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0)授权许可. 136 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 16 | 17 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 18 | 19 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 20 | 21 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 22 | 23 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 24 | 25 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 26 | 27 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 28 | 29 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 30 | 31 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 34 | 35 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 36 | 37 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 38 | You must cause any modified files to carry prominent notices stating that You changed the files; and 39 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 41 | 42 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 43 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 44 | 45 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 46 | 47 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 48 | 49 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 50 | 51 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 52 | 53 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /src/main/java/com/huawei/wallet/util/JweUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.huawei.wallet.util; 18 | 19 | import org.apache.commons.codec.binary.Base64; 20 | import org.apache.commons.codec.binary.Hex; 21 | 22 | import java.io.ByteArrayOutputStream; 23 | import java.nio.charset.StandardCharsets; 24 | import java.security.SecureRandom; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | import java.util.zip.GZIPOutputStream; 28 | 29 | /** 30 | * JWE utility class. 31 | * 32 | * @since 2020-03-02 33 | */ 34 | public class JweUtil { 35 | 36 | /** 37 | * Generate a JSON Web Encryption (JWE). 38 | * 39 | * @param jwePrivateKey private key used to sign JWE content. 40 | * @param payload information plain text. It can be a list of instance IDs or an instance. 41 | * @return return a map containing a content string and a signature string. 42 | */ 43 | public static String generateJwe(String jwePrivateKey, String payload) { 44 | // Part 1: JWE Header. 45 | // This header contains information about encryption and compression algorithms. It's a constant String. 46 | System.out.println("Part 1:"); 47 | Map jweHeader = getHeader(); 48 | String jweHeaderEncode = getEncodeHeader(jweHeader); 49 | System.out.println("Encoded header: " + jweHeaderEncode); 50 | 51 | // Part 2: JWE Encrypted Key 52 | // Generate a 16-byte session key to encrypt payload data. Then convert it to a Hex String. 53 | System.out.println("Part 2:"); 54 | String sessionKey = generateSecureRandomFactor(16); 55 | // Encrypt the session key Hex String with Huawei's fixed sessionKeyPublicKey using 56 | // RSA/NONE/OAEPwithSHA-256andMGF1Padding algorithm, and then do base64 encoding to it. 57 | System.out.println("sessionKey: " + sessionKey); 58 | String sessionKeyPublicKey = 59 | "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAgBJB4usbO33Xg5vhJqfHJsMZj44f7rxpjRuPhGy37bUBjSLXN+dS6HpxnZwSVJCtmiydjl3Inq3Mzu4SCGxfb9RIjqRRfHA7ab5p3JnJVQfTEHMHy8XcABl6EPYIJMh26kztPOKU2Mkn6yhRaCurhVUD3n9bD8omiNrR4rg442AJlNamA7vgKs65AoqBuU4NBkGHg0VWWpEHCUx/xyX6hIwqc1aD7P2f62ZHsKpNZBOek/riWhaVx3dTAa9ZS+Av3IGLOZiplhYIow9f8dlWyqs8nff9FZoJO03QhXLvOORT+lPAkW6gFzaoeMaGb40HakkZn3uvlAEKrKrtR0rZEok+N1hnboaAu8oaKK0rF1W6iNrXcFrO0rcrCsFTVF8qCa/1dFmIXwUd2M6cUzT9W0YkNyb6ZBbwEhjwBL4DNW4JfeF2Dzj0eZYlSuYV7e7e1e+XEO8lwPLAiy4bEFAWCaeuDVIhbIoBaU6xHNVQoyzct98gaOYxE4mVDqAUVmhfAgMBAAE="; 60 | String encryptedKeyEncode = getEncryptedKey(sessionKey, sessionKeyPublicKey); 61 | System.out.println("Encrypted sessionKey: " + encryptedKeyEncode); 62 | 63 | // Part 3: JWE IV 64 | // Generate a 12-byte iv. Then convert it to a Hex String, and then do base64 encoding to the Hex String. 65 | System.out.println("Part 3:"); 66 | byte[] iv = AesUtil.getIvByte(12); 67 | String ivHexStr = new String(Hex.encodeHex(iv, false)); 68 | String ivEncode = Base64.encodeBase64URLSafeString(ivHexStr.getBytes(StandardCharsets.UTF_8)); 69 | System.out.println("Encoded iv: " + ivEncode); 70 | 71 | // Part 4: JWE Cipher Text 72 | // Encrypt the payload with sessionKey and iv using AES/GCM/NoPadding algorithm. Encode the cipher text into a 73 | // Hex String. Then do gzip compression and base64 encoding to the Hex String. 74 | System.out.println("Part 4:"); 75 | System.out.println("payload: " + payload); 76 | String cipherTextEncode = getCipherText(payload, sessionKey, iv); 77 | System.out.println("Compressed and encoded cipher text: " + cipherTextEncode); 78 | 79 | // Part 5: JWE Signature 80 | // Use your own private key to sign the content with SHA256withRSA, then do base64 encoding to it. 81 | // HMS wallet server will use the public key you provided on AGC to verify signatures. 82 | System.out.println("Part 5:"); 83 | String signature = getSignature(jwePrivateKey, sessionKey, payload, jweHeaderEncode, ivEncode); 84 | System.out.println("signature: " + signature + "\n"); 85 | 86 | // Combine all five parts together to form a valid JWE. 87 | StringBuilder stringBuilder = new StringBuilder().append(jweHeaderEncode) 88 | .append(".") 89 | .append(encryptedKeyEncode) 90 | .append(".") 91 | .append(ivEncode) 92 | .append(".") 93 | .append(cipherTextEncode) 94 | .append(".") 95 | .append(signature); 96 | return stringBuilder.toString(); 97 | } 98 | 99 | private static Map getHeader() { 100 | Map jweHeader = new HashMap<>(); 101 | jweHeader.put("alg", "RSA-OAEP"); 102 | jweHeader.put("enc", "A128GCM"); 103 | jweHeader.put("kid", "1"); 104 | jweHeader.put("zip", "gzip"); 105 | return jweHeader; 106 | } 107 | 108 | private static String getEncodeHeader(Map jweHeader) { 109 | StringBuilder stringBuilder = new StringBuilder(); 110 | String headerStr = stringBuilder.append("alg=") 111 | .append(jweHeader.get("alg")) 112 | .append(", enc=") 113 | .append(jweHeader.get("enc")) 114 | .append(", kid=") 115 | .append(jweHeader.get("kid")) 116 | .append(", zip=") 117 | .append(jweHeader.get("zip")) 118 | .toString(); 119 | System.out.println("Header before encoding: " + headerStr); 120 | // Do base64 encoding. 121 | return Base64.encodeBase64URLSafeString(headerStr.getBytes(StandardCharsets.UTF_8)); 122 | } 123 | 124 | private static String getEncryptedKey(String sessionKey, String sessionKeyPublicKey) { 125 | try { 126 | String encryptedSessionKey = RsaUtil.encrypt(sessionKey.getBytes(StandardCharsets.UTF_8), 127 | sessionKeyPublicKey, "RSA/NONE/OAEPwithSHA-256andMGF1Padding"); 128 | return Base64.encodeBase64URLSafeString(encryptedSessionKey.getBytes(StandardCharsets.UTF_8)); 129 | } catch (Exception e) { 130 | throw new IllegalArgumentException("Encrypt session key failed. Error: " + e.getMessage()); 131 | } 132 | } 133 | 134 | private static String getCipherText(String dataJson, String sessionKey, byte[] iv) { 135 | String payloadEncrypt = AesUtil.encryptByGcm(dataJson, sessionKey, iv); 136 | System.out.println("Encrypted payload Hex String: " + payloadEncrypt); 137 | byte[] payLoadEncryptCompressByte = compress(payloadEncrypt.getBytes(StandardCharsets.UTF_8)); 138 | return Base64.encodeBase64URLSafeString(payLoadEncryptCompressByte); 139 | } 140 | 141 | private static String getSignature(String jweSignPrivateKey, String sessionKey, String payLoadJson, 142 | String jweHeaderEncode, String ivEncode) { 143 | StringBuilder stringBuilder = new StringBuilder(); 144 | String signContent = stringBuilder.append(jweHeaderEncode) 145 | .append(".") 146 | .append(sessionKey) 147 | .append(".") 148 | .append(ivEncode) 149 | .append(".") 150 | .append(payLoadJson) 151 | .toString(); 152 | System.out.println("Content to be signed: " + signContent); 153 | return RsaUtil.sign(signContent, jweSignPrivateKey); 154 | } 155 | 156 | /** 157 | * gzip Compress 158 | * 159 | * @param originalBytes Data to be compressed 160 | * @return Compressed data 161 | */ 162 | public static byte[] compress(byte[] originalBytes) { 163 | if (originalBytes == null || originalBytes.length == 0) { 164 | return null; 165 | } 166 | try (ByteArrayOutputStream out = new ByteArrayOutputStream(); 167 | GZIPOutputStream gzip = new GZIPOutputStream(out)) { 168 | gzip.write(originalBytes); 169 | gzip.finish(); 170 | return out.toByteArray(); 171 | } catch (Exception e) { 172 | System.out.println(e.getMessage()); 173 | return null; 174 | } 175 | } 176 | 177 | /** 178 | * Generate random hex string. 179 | * 180 | * @param size string length. 181 | * @return the generated random hex string. 182 | */ 183 | private static String generateSecureRandomFactor(int size) { 184 | SecureRandom random = new SecureRandom(); 185 | byte[] bytes = new byte[size]; 186 | random.nextBytes(bytes); 187 | return org.bouncycastle.util.encoders.Hex.toHexString(bytes); 188 | } 189 | } 190 | --------------------------------------------------------------------------------