diff --git a/pom.xml b/pom.xml index 122445fe8..cd716e686 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 manage - 1.1.11 + 1.1.12 UTF-8 diff --git a/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java b/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java index 80fd0479f..1046aebca 100644 --- a/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java +++ b/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java @@ -39,6 +39,8 @@ public interface ClientManager { JSONObject listClients(JSONObject manager, PartnerQuery query); + void exportClients(JSONObject manager,PartnerQuery query,HttpServletResponse resp); + JSONObject listClientsByApp(JSONObject manager, AppMerchantBean query); List listPartners(JSONObject manager, PartnerQuery query); diff --git a/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java b/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java index 874a73ff8..88d98677a 100644 --- a/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java +++ b/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java @@ -40,6 +40,7 @@ import au.com.royalpay.payment.manage.permission.utils.OrgCheckUtils; import au.com.royalpay.payment.manage.signin.beans.TodoNotice; import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider; import au.com.royalpay.payment.manage.signin.core.SignInAccountService; +import au.com.royalpay.payment.manage.support.serverless.ServerlessFunctionTrigger; import au.com.royalpay.payment.manage.support.sms.SmsSender; import au.com.royalpay.payment.manage.system.core.ClientContractService; import au.com.royalpay.payment.manage.system.core.MailGunService; @@ -281,6 +282,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid @Resource private CommonSubMerchantIdMapper commonSubMerchantIdMapper; @Resource + private ServerlessFunctionTrigger serverlessFunctionTrigger; + @Resource private Locker locker; @Resource private MongoTemplate mongoTemplate; @@ -346,27 +349,27 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid } String same_phone = clientMapper.findSamePhone(client.getString("contact_phone")).getString("a"); - if(same_phone!=null&& client.getString("contact_phone")!= null&&same_phone.contains(" ") ) { - same_phone = same_phone.replace(client.getString("client_moniker"),""); - client.put("same_phone","(雷同商户:"+same_phone+")" ); + if (same_phone != null && client.getString("contact_phone") != null && same_phone.contains(" ")) { + same_phone = same_phone.replace(client.getString("client_moniker"), ""); + client.put("same_phone", "(雷同商户:" + same_phone + ")"); } String same_company_name = clientMapper.findSameCompanyName(client.getString("company_name")).getString("a"); - if(same_company_name!=null&& client.getString("company_name")!= null&&same_company_name.contains(" ") ) { - same_company_name = same_company_name.replace(client.getString("client_moniker"),""); - client.put("same_company_name","(雷同商户:"+same_company_name+")" ); + if (same_company_name != null && client.getString("company_name") != null && same_company_name.contains(" ")) { + same_company_name = same_company_name.replace(client.getString("client_moniker"), ""); + client.put("same_company_name", "(雷同商户:" + same_company_name + ")"); } String same_email = clientMapper.findSameEmail(client.getString("contact_email")).getString("a"); - if(same_email!=null&& client.getString("contact_email")!= null&&same_email.contains(" ") ) { - same_email = same_email.replace(client.getString("client_moniker"),""); - client.put("same_email","(雷同商户:"+same_email+")" ); + if (same_email != null && client.getString("contact_email") != null && same_email.contains(" ")) { + same_email = same_email.replace(client.getString("client_moniker"), ""); + client.put("same_email", "(雷同商户:" + same_email + ")"); } String same_address = clientMapper.findSameAddress(client.getString("address")).getString("a"); - if(same_address!=null&& client.getString("address")!= null&&same_address.contains(" ") ) { - same_address = same_address.replace(client.getString("client_moniker"),""); - client.put("same_address","(雷同商户:"+same_address+")" ); + if (same_address != null && client.getString("address") != null && same_address.contains(" ")) { + same_address = same_address.replace(client.getString("client_moniker"), ""); + client.put("same_address", "(雷同商户:" + same_address + ")"); } @@ -445,8 +448,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid } //商户支付场景 if (StringUtils.isNotBlank(client.getString("client_pay_type"))) { - client.put("client_pay_type",client.getString("client_pay_type").split(",")); - client.put("client_pay_desc",client.getString("client_pay_desc").split(",")); + client.put("client_pay_type", client.getString("client_pay_type").split(",")); + client.put("client_pay_desc", client.getString("client_pay_desc").split(",")); } if (StringUtils.isNotBlank(client.getString("parent_client_id")) && sysClientMapper.childClientId(client.getIntValue("client_id")).size() > 0) { @@ -487,6 +490,39 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid @Override public JSONObject listClients(JSONObject manager, PartnerQuery query) { + JSONObject params = prepareListClientsParameter(manager, query); + PageList partners = clientMapper.listPartners(params, + new PageBounds(query.getPage(), query.getLimit(), Order.formString("is_valid.desc,-approve_time.asc,create_time.desc"))); + int authDays = PlatformEnvironment.getEnv().authDays();// 快速自助开通申请有效期 + for (JSONObject partner : partners) { + String subMerchantId = partner.getString("sub_merchant_id"); + if (subMerchantId != null) { + partner.put("temp_sub_merchant", checkSubMerchantIdInCommonPool(subMerchantId)); + } + if (partner.getIntValue("approve_result") == 2) { + partner.put("expiry_time", DateUtils.addDays(partner.getDate("approve_time"), authDays)); + partner.put("pass_timeout", DateUtils.addDays(partner.getDate("approve_time"), authDays).compareTo(new Date()) < 0); + } + } + return PageListUtils.buildPageListResult(partners); + } + + @Override + public void exportClients(JSONObject manager, PartnerQuery query, HttpServletResponse resp) { + JSONObject params = prepareListClientsParameter(manager, query); + JSONObject retResp = serverlessFunctionTrigger.triggerFunction("export_merchants", params); + String contentB64 = retResp.getString("content"); + resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + resp.setHeader("Content-Disposition", "attachment; filename=merchants.xlsx"); + try (OutputStream out = resp.getOutputStream()) { + IOUtils.write(Base64.decodeBase64(contentB64), out); + out.flush(); + } catch (IOException e) { + throw new ServerErrorException(e); + } + } + + private JSONObject prepareListClientsParameter(JSONObject manager, PartnerQuery query) { JSONObject params = query.toJsonParam(); if (params.getString("org_id") != null) { if (params.getString("org_ids") == null) { @@ -549,20 +585,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid params.put("temp_mch_id", tempSubMchId); params.put("temp_mch_id_source", tempSubMchSource); } - PageList partners = clientMapper.listPartners(params, - new PageBounds(query.getPage(), query.getLimit(), Order.formString("is_valid.desc,-approve_time.asc,create_time.desc"))); - int authDays = PlatformEnvironment.getEnv().authDays();// 快速自助开通申请有效期 - for (JSONObject partner : partners) { - String subMerchantId = partner.getString("sub_merchant_id"); - if (subMerchantId != null) { - partner.put("temp_sub_merchant", checkSubMerchantIdInCommonPool(subMerchantId)); - } - if (partner.getIntValue("approve_result") == 2) { - partner.put("expiry_time", DateUtils.addDays(partner.getDate("approve_time"), authDays)); - partner.put("pass_timeout", DateUtils.addDays(partner.getDate("approve_time"), authDays).compareTo(new Date()) < 0); - } - } - return PageListUtils.buildPageListResult(partners); + return params; } @Override @@ -797,7 +820,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid JSONObject clientConfig = new JSONObject(); clientConfig.put("client_id", clientId); clientConfig.put("client_moniker", client.getString("client_moniker")); - if (StringUtils.isNotBlank(updateInfo.getString("client_pay_type"))&& StringUtils.isNotBlank(updateInfo.getString("client_pay_desc"))) { + if (StringUtils.isNotBlank(updateInfo.getString("client_pay_type")) && StringUtils.isNotBlank(updateInfo.getString("client_pay_desc"))) { clientConfig.put("client_pay_type", updateInfo.getString("client_pay_type")); clientConfig.put("client_pay_desc", updateInfo.getString("client_pay_desc")); } @@ -3481,7 +3504,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid throw new ForbiddenException("Cashier has no permission to switch retail surcharge"); } clientModifySupport - .processClientConfigModify(new SwitchPermissionModify(account, client.getString("client_moniker"), "cbbank_surcharge", paySurcharge),true); + .processClientConfigModify(new SwitchPermissionModify(account, client.getString("client_moniker"), "cbbank_surcharge", paySurcharge), true); } @Override @@ -5167,6 +5190,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid } }); } + private TemplateMessage initSendTestPasswordTemplate(String wxopenid, String templateId) { TemplateMessage msg = new TemplateMessage(wxopenid, templateId, PlatformEnvironment.getEnv().concatUrl("testMerchantPassword")); msg.put("first", "系统测试商户账户已重置", "#000000"); diff --git a/src/main/java/au/com/royalpay/payment/manage/merchants/web/PartnerManageController.java b/src/main/java/au/com/royalpay/payment/manage/merchants/web/PartnerManageController.java index b32ff4b9b..31103b707 100644 --- a/src/main/java/au/com/royalpay/payment/manage/merchants/web/PartnerManageController.java +++ b/src/main/java/au/com/royalpay/payment/manage/merchants/web/PartnerManageController.java @@ -43,6 +43,11 @@ public class PartnerManageController { return clientManager.listClients(manager, query); } + @ManagerMapping(value = "/exporting_excel", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.FINANCIAL_STAFF}) + public void exportClientsExcel(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, PartnerQuery query, HttpServletResponse resp) { + clientManager.exportClients(manager, query, resp); + } + @RequestMapping(value = "/list", method = RequestMethod.GET) @RequireManager(role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.DIRECTOR}) public List lisPartners(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, PartnerQuery query) { @@ -94,7 +99,7 @@ public class PartnerManageController { response.setContentType("application/octet-stream;"); response.addHeader("Content-Disposition", "attachment; filename=qr_board.jpg"); OutputStream ous = response.getOutputStream(); - clientManager.writeQrCodeBoard(manager, clientMoniker, config, ous,"PC"); + clientManager.writeQrCodeBoard(manager, clientMoniker, config, ous, "PC"); } @ManagerMapping(value = "/{clientMoniker}/qrcode_board/aggregate", method = RequestMethod.GET) @@ -103,16 +108,16 @@ public class PartnerManageController { response.setContentType("application/octet-stream;"); response.addHeader("Content-Disposition", "attachment; filename=qr_board.jpg"); OutputStream ous = response.getOutputStream(); - clientManager.writeAggregateQrCodeBoard(manager, clientMoniker, config, ous,"PC"); + clientManager.writeAggregateQrCodeBoard(manager, clientMoniker, config, ous, "PC"); } @ManagerMapping(value = "/{clientMoniker}/qrcode_board/CBBankAggregate", method = RequestMethod.GET) public void getCBBankAggregateQRCodeBoardImage(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { response.setContentType("application/octet-stream;"); response.addHeader("Content-Disposition", "attachment; filename=qr_board.jpg"); OutputStream ous = response.getOutputStream(); - clientManager.writeCBBankAggregateQrCodeBoard(manager, clientMoniker, ous,"PC"); + clientManager.writeCBBankAggregateQrCodeBoard(manager, clientMoniker, ous, "PC"); } @ManagerMapping(value = "/{clientMoniker}/poster", method = RequestMethod.GET) @@ -141,18 +146,18 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/max_order_amount", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR}) - public void setMaxOrderAmount(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject limit) { - clientManager.setMaxOrderAmount(manager,clientMoniker, limit.getBigDecimal("limit")); + public void setMaxOrderAmount(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject limit) { + clientManager.setMaxOrderAmount(manager, clientMoniker, limit.getBigDecimal("limit")); } @ManagerMapping(value = "/{clientMoniker}/customer_surcharge_rate", method = RequestMethod.PUT, role = {ManagerRole.ADMIN}) - public void setCustomerSurchargeRate(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setCustomerSurchargeRate(manager,clientMoniker, config.getBigDecimal("customer_surcharge_rate")); + public void setCustomerSurchargeRate(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setCustomerSurchargeRate(manager, clientMoniker, config.getBigDecimal("customer_surcharge_rate")); } @ManagerMapping(value = "/{clientMoniker}/order_expiry_config", method = RequestMethod.PUT, role = {ManagerRole.ADMIN}) - public void setOrderExpiryConfig(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setOrderExpiryConfig(manager,clientMoniker, config.getString("order_expiry_config")); + public void setOrderExpiryConfig(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setOrderExpiryConfig(manager, clientMoniker, config.getString("order_expiry_config")); } @ManagerMapping(value = "/{clientMoniker}", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR}) @@ -207,43 +212,43 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/qrcode_surcharge", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.SERVANT}) - public void setClientPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientQRCodePaySurCharge(manager,clientMoniker, config.getBooleanValue("qrcode_surcharge")); + public void setClientPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientQRCodePaySurCharge(manager, clientMoniker, config.getBooleanValue("qrcode_surcharge")); } @ManagerMapping(value = "/{clientMoniker}/gateway_upgrade", method = RequestMethod.PUT, role = {ManagerRole.DEVELOPER}) - public void enableGatewayUpgrade(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.enableGatewayUpgrade(manager,clientMoniker, config.getBooleanValue("gateway_upgrade")); + public void enableGatewayUpgrade(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.enableGatewayUpgrade(manager, clientMoniker, config.getBooleanValue("gateway_upgrade")); } @ManagerMapping(value = "/{clientMoniker}/gateway_alipay_online", method = RequestMethod.PUT, role = {ManagerRole.DEVELOPER}) - public void enableGatewayAlipayOnline(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.enableGatewayAlipayOnline(manager,clientMoniker, config.getBooleanValue("gateway_alipay_online")); + public void enableGatewayAlipayOnline(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.enableGatewayAlipayOnline(manager, clientMoniker, config.getBooleanValue("gateway_alipay_online")); } @ManagerMapping(value = "/{clientMoniker}/api_surcharge", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.SERVANT}) - public void setClientApiPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientApiPaySurCharge(manager,clientMoniker, config.getBooleanValue("api_surcharge")); + public void setClientApiPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientApiPaySurCharge(manager, clientMoniker, config.getBooleanValue("api_surcharge")); } @ManagerMapping(value = "/{clientMoniker}/retail_surcharge", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.SERVANT}) - public void setClientRetailPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientRetailPaySurCharge(manager,clientMoniker, config.getBooleanValue("retail_surcharge")); + public void setClientRetailPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientRetailPaySurCharge(manager, clientMoniker, config.getBooleanValue("retail_surcharge")); } @ManagerMapping(value = "/{clientMoniker}/cbbank_surcharge", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.BD_USER}) - public void setClientCBBankPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientCBBankPaySurCharge(manager,clientMoniker, config.getBooleanValue("cbbank_surcharge")); + public void setClientCBBankPaySurCharge(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientCBBankPaySurCharge(manager, clientMoniker, config.getBooleanValue("cbbank_surcharge")); } @ManagerMapping(value = "/{clientMoniker}/tax_in_surcharge", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void setClientTaxPayer(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientTaxInSurcharge(manager,clientMoniker, config.getBooleanValue("tax_in_surcharge")); + public void setClientTaxPayer(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientTaxInSurcharge(manager, clientMoniker, config.getBooleanValue("tax_in_surcharge")); } @ManagerMapping(value = "/{clientMoniker}/customer_tax_free", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR}) - public void setClientCustomerTaxFree(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject config) { - clientManager.setClientCustomerTaxFree(manager,clientMoniker, config.getBooleanValue("customer_tax_free")); + public void setClientCustomerTaxFree(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject config) { + clientManager.setClientCustomerTaxFree(manager, clientMoniker, config.getBooleanValue("customer_tax_free")); } @ManagerMapping(value = "/{clientMoniker}/credential_code", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER}) @@ -283,6 +288,7 @@ public class PartnerManageController { /** * 父商户全局管理子商户 + * * @param clientMoniker * @param pass * @param manager @@ -294,7 +300,7 @@ public class PartnerManageController { @ManagerMapping(value = "/{clientMoniker}/child_each_refund", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR}) public void switchChildEachRefund(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.switchChildEachRefund(manager, clientMoniker, pass.getBooleanValue("allow")); + clientManager.switchChildEachRefund(manager, clientMoniker, pass.getBooleanValue("allow")); } @ManagerMapping(value = "/{clientMoniker}/channels/{channel}/permission", method = RequestMethod.PUT, role = {ManagerRole.SERVANT, ManagerRole.DEVELOPER}) @@ -328,7 +334,7 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/reset/refund_pwd", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.DEVELOPER}) - public void changeRefundPwd(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@RequestBody JSONObject config) { + public void changeRefundPwd(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @RequestBody JSONObject config) { clientManager.resetRefundPasswordByManage(clientMoniker, manager, config); } @@ -363,7 +369,7 @@ public class PartnerManageController { return tradeLogService.listOrderRefunds(orderId, null); } - @ManagerMapping(value = "/{clientMoniker}/accounts", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.DIRECTOR,ManagerRole.DEVELOPER}) + @ManagerMapping(value = "/{clientMoniker}/accounts", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.DIRECTOR, ManagerRole.DEVELOPER}) public List partnerAccounts(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { return clientManager.listAccounts(manager, clientMoniker); } @@ -411,8 +417,8 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/skip_clearing", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.FINANCIAL_STAFF}) - public void skipClearing(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@PathVariable String clientMoniker, @RequestBody JSONObject skip_clearing) { - clientManager.setSkipClearing(manager,clientMoniker, skip_clearing.getBooleanValue("skip_clearing"),skip_clearing.getString("remark")); + public void skipClearing(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject skip_clearing) { + clientManager.setSkipClearing(manager, clientMoniker, skip_clearing.getBooleanValue("skip_clearing"), skip_clearing.getString("remark")); } @ManagerMapping(value = "/{clientMoniker}/surcharge_mode", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) @@ -501,7 +507,7 @@ public class PartnerManageController { @RequestParam(required = false) String[] client_ids, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int limit, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - return clientManager.listClientDevices(manager, clientMoniker, remark, page, limit,client_type,client_ids); + return clientManager.listClientDevices(manager, clientMoniker, remark, page, limit, client_type, client_ids); } //给商户新增设备 @@ -567,7 +573,7 @@ public class PartnerManageController { @ManagerMapping(value = "/{clientMoniker}/export/aggregate/agreepdf", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.DIRECTOR, ManagerRole.OPERATOR}) public void exportAggregateAgreeFile(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) throws Exception { - clientManager.getAggregateAgreeFile(clientMoniker, manager,false); + clientManager.getAggregateAgreeFile(clientMoniker, manager, false); } @ManagerMapping(value = "/{clientMoniker}/temp/export/pdf", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.DIRECTOR, ManagerRole.OPERATOR}) @@ -577,7 +583,7 @@ public class PartnerManageController { @ManagerMapping(value = "/{clientMoniker}/import/agreepdf", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.DIRECTOR, ManagerRole.OPERATOR}) public void importAgreeFile(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @RequestBody JSONObject source) throws Exception { - clientManager.importAgreeFile(clientMoniker, manager, source.getString("source_agree_file"),false); + clientManager.importAgreeFile(clientMoniker, manager, source.getString("source_agree_file"), false); } @ManagerMapping(value = "/{clientMoniker}/notify/completeAgree", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) @@ -628,19 +634,19 @@ public class PartnerManageController { merchantLocationService.updateMerchantLocation(manager, clientMoniker, geoData); } - @ManagerMapping(value = "/{clientMoniker}/wechat_compliance_permission",method = RequestMethod.PUT,role = {ManagerRole.OPERATOR,ManagerRole.ADMIN}) + @ManagerMapping(value = "/{clientMoniker}/wechat_compliance_permission", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) public void wechatCcompliancePermission(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { clientManager.switchPermission(manager, clientMoniker, "wechat_compliance", pass.getBooleanValue("allow")); } - @ManagerMapping(value = "/{clientMoniker}/local_merchant_permission",method = RequestMethod.PUT,role = {ManagerRole.OPERATOR,ManagerRole.ADMIN}) + @ManagerMapping(value = "/{clientMoniker}/local_merchant_permission", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) public void localMerchantPermission(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { clientManager.switchPermission(manager, clientMoniker, "local_merchant", pass.getBooleanValue("allow")); } - @ManagerMapping(value = "/{clientMoniker}/list_sub_applices",method = RequestMethod.GET,role = {ManagerRole.OPERATOR,ManagerRole.ADMIN}) + @ManagerMapping(value = "/{clientMoniker}/list_sub_applices", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) public List listSubMerchantIdApplys(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - return clientManager.listSubMerchantIdApplys(manager,clientMoniker); + return clientManager.listSubMerchantIdApplys(manager, clientMoniker); } @ManagerMapping(value = "/{clientMoniker}/list_rpay_sub_applices", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) @@ -655,56 +661,57 @@ public class PartnerManageController { @ManagerMapping(value = "/{clientMoniker}/sub_apply", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) public String subMerchantApplication(@PathVariable String clientMoniker, @RequestBody SubMerchantIdApply subMerchantIdApply, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - return clientManager.subMerchantApplication(clientMoniker,subMerchantIdApply,manager); + return clientManager.subMerchantApplication(clientMoniker, subMerchantIdApply, manager); } @ManagerMapping(value = "/{clientMoniker}/register/alipay_gms", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void registerAlipayGms(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public void registerAlipayGms(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { clientManager.registerAlipayGms(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/query/alipay_gms", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public String queryAlipayGmsStatus(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public String queryAlipayGmsStatus(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { return clientManager.queryAlipayGmsStatus(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/register/alipayOnline_gms", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void registerAlipayOnlineGms(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public void registerAlipayOnlineGms(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { clientManager.registerAlipayOnlineGms(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/query/alipayOnline_gms", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public String queryAlipayOnlineGmsStatus(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public String queryAlipayOnlineGmsStatus(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { return clientManager.queryAlipayOnlineGmsStatus(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/query/alipay_gms_json", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public JSONObject queryAlipayGmsJson(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public JSONObject queryAlipayGmsJson(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { return clientManager.queryAlipayGmsJson(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/query/alipayOnline_gms_json", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public JSONObject queryAlipayOnlineGmsJson(@PathVariable String clientMoniker,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + public JSONObject queryAlipayOnlineGmsJson(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { return clientManager.queryAlipayOnlineGmsJson(clientMoniker, manager); } - @ManagerMapping(value = "/{clientMoniker}/get_merchant_ids",method = RequestMethod.GET,role = {ManagerRole.OPERATOR,ManagerRole.ADMIN}) + @ManagerMapping(value = "/{clientMoniker}/get_merchant_ids", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) public List getMerchantIds(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - return clientManager.listMerchantIds(clientMoniker,manager); + return clientManager.listMerchantIds(clientMoniker, manager); } - @ManagerMapping(value = "/{clientMoniker}/get_sub_merchant_id_logs",method = RequestMethod.GET,role = {ManagerRole.OPERATOR}) + @ManagerMapping(value = "/{clientMoniker}/get_sub_merchant_id_logs", method = RequestMethod.GET, role = {ManagerRole.OPERATOR}) public List getClientSubMerchantIdLogs(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - return clientManager.getClientSubMerchantIdLogs(clientMoniker,manager); + return clientManager.getClientSubMerchantIdLogs(clientMoniker, manager); } - @ManagerMapping(value = "/unsub/{clientMoniker}",method = RequestMethod.PUT,role = {ManagerRole.OPERATOR}) + + @ManagerMapping(value = "/unsub/{clientMoniker}", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR}) public void addSub(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.addSub(clientMoniker,manager); + clientManager.addSub(clientMoniker, manager); } - @ManagerMapping(value = "/unsub/{clientMoniker}",method = RequestMethod.DELETE,role = {ManagerRole.OPERATOR}) + @ManagerMapping(value = "/unsub/{clientMoniker}", method = RequestMethod.DELETE, role = {ManagerRole.OPERATOR}) public void removeSub(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.removeSub(clientMoniker,manager); + clientManager.removeSub(clientMoniker, manager); } @ManagerMapping(value = "/{clientMoniker}/hf", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) @@ -718,32 +725,32 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/{channel}", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) - public void switchGateWayLinkPermission(@PathVariable String clientMoniker, @PathVariable String channel,@RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.switchGatewayLink(manager, clientMoniker, channel,pass.getBooleanValue("allow")); + public void switchGateWayLinkPermission(@PathVariable String clientMoniker, @PathVariable String channel, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.switchGatewayLink(manager, clientMoniker, channel, pass.getBooleanValue("allow")); } @ManagerMapping(value = "/{clientMoniker}/{channel}/email_notice", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER}) - public void switchGatewayEmailNotice(@PathVariable String clientMoniker, @PathVariable String channel,@RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.switchPermission(manager, clientMoniker,"enable_"+channel+"_email_notice", pass.getBooleanValue("allow")); + public void switchGatewayEmailNotice(@PathVariable String clientMoniker, @PathVariable String channel, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.switchPermission(manager, clientMoniker, "enable_" + channel + "_email_notice", pass.getBooleanValue("allow")); } @ManagerMapping(value = "/{clientMoniker}/registRpaySubMerchantId", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void subRpayMerchantApplication(@PathVariable String clientMoniker,@RequestBody JSONObject merchantInfo,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.subRpayMerchantApplication(clientMoniker, merchantInfo,manager); + public void subRpayMerchantApplication(@PathVariable String clientMoniker, @RequestBody JSONObject merchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.subRpayMerchantApplication(clientMoniker, merchantInfo, manager); } @ManagerMapping(value = "/{clientMoniker}/registYeepaySubMerchantId", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void subYeepayMerchantApplication(@PathVariable String clientMoniker,@RequestBody JSONObject merchantInfo,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.subYeepayMerchantApplication(clientMoniker, merchantInfo,manager); + public void subYeepayMerchantApplication(@PathVariable String clientMoniker, @RequestBody JSONObject merchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.subYeepayMerchantApplication(clientMoniker, merchantInfo, manager); } @ManagerMapping(value = "/{clientMoniker}/updateYeepaySubMerchantId", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void reSubYeepayMerchantApplication(@PathVariable String clientMoniker,@RequestBody JSONObject merchantInfo,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.reSubYeepayMerchantApplication(clientMoniker, merchantInfo,manager); + public void reSubYeepayMerchantApplication(@PathVariable String clientMoniker, @RequestBody JSONObject merchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.reSubYeepayMerchantApplication(clientMoniker, merchantInfo, manager); } @RequestMapping(value = "/compliance", method = RequestMethod.GET) - @RequireManager(role = { ManagerRole.OPERATOR}) + @RequireManager(role = {ManagerRole.OPERATOR}) public JSONObject lisPartnersByCompliance(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, PartnerQuery query) { return clientManager.comListPartnerSelection(manager, query); } @@ -765,8 +772,8 @@ public class PartnerManageController { } @ManagerMapping(value = "/{clientMoniker}/addYeepaySubMerchantId", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN}) - public void subYeepayMerchantAdd(@PathVariable String clientMoniker,@RequestBody JSONObject merchantInfo,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { - clientManager.subYeepayMerchantAdd(clientMoniker, merchantInfo,manager); + public void subYeepayMerchantAdd(@PathVariable String clientMoniker, @RequestBody JSONObject merchantInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.subYeepayMerchantAdd(clientMoniker, merchantInfo, manager); } @RequestMapping(value = "/{clientMoniker}/cb_bankpay/link/pc", method = RequestMethod.GET) @@ -777,11 +784,12 @@ public class PartnerManageController { /** * 商户设置单独的网银和快捷通道 + * * @param clientMoniker * @param channelKey * @throws IOException */ - @ManagerMapping(value = "/{clientMoniker}/cb_bankpay/{channelKey}/channel_id", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) + @ManagerMapping(value = "/{clientMoniker}/cb_bankpay/{channelKey}/channel_id", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR}) public void switchPartnerCBChannelConfig(@PathVariable String clientMoniker, @PathVariable String channelKey, @RequestBody JSONObject channel) { clientManager.partnerCBChannelConfig(clientMoniker, channelKey, channel.getString("channel_id")); } diff --git a/src/main/java/au/com/royalpay/payment/manage/support/serverless/ServerlessFunctionTrigger.java b/src/main/java/au/com/royalpay/payment/manage/support/serverless/ServerlessFunctionTrigger.java new file mode 100644 index 000000000..8d5e9fdb4 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/support/serverless/ServerlessFunctionTrigger.java @@ -0,0 +1,11 @@ +package au.com.royalpay.payment.manage.support.serverless; + +import com.alibaba.fastjson.JSONObject; + +/** + * Create by davep at 2019-08-08 15:56 + */ +public interface ServerlessFunctionTrigger { + + JSONObject triggerFunction(String function,JSONObject params); +} diff --git a/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/QCloudServerlessTrigger.java b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/QCloudServerlessTrigger.java new file mode 100644 index 000000000..4e680c42a --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/QCloudServerlessTrigger.java @@ -0,0 +1,63 @@ +package au.com.royalpay.payment.manage.support.serverless.qcloud; + +import au.com.royalpay.payment.manage.support.serverless.ServerlessFunctionTrigger; +import au.com.royalpay.payment.manage.support.serverless.qcloud.support.ServerLessFunctionInvokeRequest; +import au.com.royalpay.payment.tools.exceptions.ServerErrorException; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; + +/** + * Create by davep at 2019-08-12 9:31 + */ +@Service +public class QCloudServerlessTrigger implements ServerlessFunctionTrigger { + private Logger logger = LoggerFactory.getLogger(getClass()); + private RestTemplate restTemplate; + private String secretId; + private String secretKey; + private String region; + + public QCloudServerlessTrigger(@Value("${qcloud.secret-id}") String secretId, + @Value("${qcloud.secret-key}") String secretKey, + @Value("${qcloud.scf.region}") String region) { + this.secretId = secretId; + this.secretKey = secretKey; + this.region = region; + this.restTemplate = new RestTemplateBuilder() + .messageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8)) + .build(); + } + + + @Override + public JSONObject triggerFunction(String function, JSONObject params) { + ServerLessFunctionInvokeRequest request = new ServerLessFunctionInvokeRequest(secretId, secretKey, region, function, params); + ResponseEntity resp = restTemplate.exchange(request.request(), String.class); + JSONObject data = JSON.parseObject(resp.getBody()); + JSONObject response = data.getJSONObject("Response"); + String requestId = response.getString("RequestId"); + JSONObject result = response.getJSONObject("Result"); + int invokeResult = result.getIntValue("InvokeResult"); + if (invokeResult != 0) { + String errMsg = result.getString("ErrMsg"); + logger.error("Invoking function [{}] failed,request id={},invoke result={},errMsg={}", function, requestId, invokeResult, errMsg); + throw new ServerErrorException("Invoke function " + function + " failed:[" + errMsg + "]"); + } else { + String retMsg = result.getString("RetMsg"); + return StringUtils.isNotEmpty(retMsg) ? JSON.parseObject(retMsg) : null; + } + } + + +} diff --git a/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/QCloudV3Request.java b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/QCloudV3Request.java new file mode 100644 index 000000000..1adec2cd1 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/QCloudV3Request.java @@ -0,0 +1,135 @@ +package au.com.royalpay.payment.manage.support.serverless.qcloud.support; + +import au.com.royalpay.payment.tools.exceptions.ServerErrorException; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.http.RequestEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Create by davep at 2019-08-12 15:06 + */ +public abstract class QCloudV3Request { + private static Logger logger = LoggerFactory.getLogger(QCloudV3Request.class); + private static final String ALGORITHM = "TC3-HMAC-SHA256"; + private String secretId; + private String secretKey; + private String region; + private MultiValueMap headers = new LinkedMultiValueMap<>(); + + + public QCloudV3Request(String secretId, String secretKey, String region) { + this.secretId = secretId; + this.secretKey = secretKey; + this.region = region; + headers.add("host", host()); + headers.add("content-type", contentType()); + } + + protected abstract String host(); + + protected abstract String uri(); + + protected abstract HttpMethod method(); + + protected abstract String action(); + + protected abstract String version(); + + protected abstract String contentType(); + + protected abstract String requestPayload(); + + protected abstract String queryStringParams(); + + protected String service() { + return StringUtils.substringBefore(host(), "."); + } + + public void setHeader(String name, String value) { + headers.add(name, value); + } + + public RequestEntity request() { + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl("https://" + host() + uri()); + String queryStr = queryStringParams(); + if (StringUtils.isNotEmpty(queryStr)) { + uriBuilder = uriBuilder.query(queryStr); + } + URI url = uriBuilder.build(false).toUri(); + RequestEntity.BodyBuilder builder = RequestEntity.method(method(), url); + MultiValueMap signHeaders = buildSignature(); + for (Map.Entry> entry : signHeaders.entrySet()) { + builder = builder.header(entry.getKey(), entry.getValue().toArray(new String[0])); + } + return builder.body(requestPayload()); + } + + private MultiValueMap buildSignature() { + String timestamp = System.currentTimeMillis() / 1000 + ""; + String date = DateTime.now(DateTimeZone.UTC).toString("yyyy-MM-dd"); + // ************* 步骤 1:拼接规范请求串 ************* + String httpRequestMethod = method().name(); + String canonicalUri = uri(); + String canonicalQueryString = queryStringParams(); + String canonicalHeaders = headers.entrySet().stream() + .flatMap(nameEntry -> nameEntry.getValue().stream() + .map(v -> nameEntry.getKey().toLowerCase() + ":" + v + "\n")) + .sorted() + .collect(Collectors.joining()); + String signedHeaders = headers.keySet().stream().map(String::toLowerCase).sorted().collect(Collectors.joining(";")); + String hashedRequestPayload = DigestUtils.sha256Hex(requestPayload()); + String canonicalRequest = String.join("\n", httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders, hashedRequestPayload); + logger.info("request:\n{}", canonicalRequest); + // ************* 步骤 2:拼接待签名字符串 ************* + String credentialScope = date + "/" + service() + "/tc3_request"; + String hashedCanonicalRequest = DigestUtils.sha256Hex(canonicalRequest.getBytes(StandardCharsets.UTF_8)); + String stringToSign = String.join("\n", ALGORITHM, timestamp, credentialScope, hashedCanonicalRequest); + logger.info("to sign:\n{}", stringToSign); + // ************* 步骤 3:计算签名 ************* + byte[] secretDate = sign256(("TC3" + secretKey).getBytes(StandardCharsets.UTF_8), date); + byte[] secretService = sign256(secretDate, service()); + byte[] secretSigning = sign256(secretService, "tc3_request"); + String signature = Hex.encodeHexString(sign256(secretSigning, stringToSign)).toLowerCase(); + String authorization = String.format("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s", + ALGORITHM, secretId, credentialScope, signedHeaders, signature); + + MultiValueMap signHeaders = new LinkedMultiValueMap<>(headers); + signHeaders.set("Authorization", authorization); + signHeaders.set("X-TC-Action", action()); + signHeaders.set("X-TC-Timestamp", timestamp); + signHeaders.set("X-TC-Version", version()); + signHeaders.set("X-TC-Region", region); + return signHeaders; + } + + private static byte[] sign256(byte[] key, String msg) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm()); + mac.init(secretKeySpec); + return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8)); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + logger.error(e.getMessage(), e); + throw new ServerErrorException(e); + } + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/ServerLessFunctionInvokeRequest.java b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/ServerLessFunctionInvokeRequest.java new file mode 100644 index 000000000..c4302a0cc --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/support/serverless/qcloud/support/ServerLessFunctionInvokeRequest.java @@ -0,0 +1,62 @@ +package au.com.royalpay.payment.manage.support.serverless.qcloud.support; + +import com.alibaba.fastjson.JSONObject; +import org.springframework.http.HttpMethod; +import org.springframework.util.MimeTypeUtils; + +/** + * Create by davep at 2019-08-12 17:13 + */ +public class ServerLessFunctionInvokeRequest extends QCloudV3Request { + private final String functionName; + private final JSONObject clientContext; + + public ServerLessFunctionInvokeRequest(String secretId, String secretKey, String region, String functionName, JSONObject clientContext) { + super(secretId, secretKey, region); + this.functionName = functionName; + this.clientContext = clientContext == null ? new JSONObject() : clientContext; + } + + @Override + protected String host() { + return "scf.tencentcloudapi.com"; + } + + @Override + protected String uri() { + return "/"; + } + + @Override + protected HttpMethod method() { + return HttpMethod.POST; + } + + @Override + protected String action() { + return "Invoke"; + } + + @Override + protected String version() { + return "2018-04-16"; + } + + @Override + protected String contentType() { + return MimeTypeUtils.APPLICATION_JSON_VALUE; + } + + @Override + protected String requestPayload() { + JSONObject data = new JSONObject(); + data.put("FunctionName", functionName); + data.put("ClientContext", clientContext.toJSONString()); + return data.toJSONString(); + } + + @Override + protected String queryStringParams() { + return ""; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d177ae586..b2810ea7e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -144,3 +144,6 @@ app.hanyin-secure.sftp-port=28480 app.hanyin-secure.sftp-username=royalpay app.hanyin-secure.sftp-pwd=royalpay +qcloud.secret-id=AKIDlHdjgWzZliPvBauZFfrnW0MaZOyHdTPz +qcloud.secret-key=YswoQDsIZfWEqEAEvMXS8Yic84lFn9Jp +qcloud.scf.region=ap-hongkong \ No newline at end of file diff --git a/src/test/java/au/com/royalpay/payment/manage/valid/QCloudSignTest.java b/src/test/java/au/com/royalpay/payment/manage/valid/QCloudSignTest.java new file mode 100644 index 000000000..e10e6aac4 --- /dev/null +++ b/src/test/java/au/com/royalpay/payment/manage/valid/QCloudSignTest.java @@ -0,0 +1,81 @@ +package au.com.royalpay.payment.manage.valid; + +import au.com.royalpay.payment.manage.support.serverless.qcloud.support.ServerLessFunctionInvokeRequest; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.RandomUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.net.util.Base64; +import org.junit.Test; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Create by davep at 2019-08-08 16:21 + */ +public class QCloudSignTest { + + private String function = "export_merchants"; + private String region = "ap-hongkong"; + private String secretId = "AKIDlHdjgWzZliPvBauZFfrnW0MaZOyHdTPz"; + private String secretKey = "YswoQDsIZfWEqEAEvMXS8Yic84lFn9Jp"; + + @Test + public void printUrl() throws NoSuchAlgorithmException, InvalidKeyException { + String host = "scf.tencentcloudapi.com/"; + String method = "GET"; + Map paramsMap = new HashMap<>(); + paramsMap.put("Action", "Invoke"); + paramsMap.put("Version", "2018-04-16"); + paramsMap.put("Region", region); + paramsMap.put("FunctionName", function); + paramsMap.put("ClientContext", "{\"client_moniker\":\"PINE\"}"); + paramsMap.put("Nonce", "" + RandomUtils.nextInt(0, 999999)); + paramsMap.put("Timestamp", "" + System.currentTimeMillis() / 1000); + paramsMap.put("SignatureMethod", "HmacSHA256"); + paramsMap.put("SecretId", secretId); + + String[] params = paramsMap.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toArray(String[]::new); + + Arrays.sort(params); + String base = method + host + "?" + StringUtils.join(params, "&"); + String key = secretKey; + + Mac sha256HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + sha256HMAC.init(secretKey); + byte[] finalBytes = sha256HMAC.doFinal(base.getBytes()); + String sign = Base64.encodeBase64String(finalBytes); + paramsMap.put("Signature", sign); + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://" + host); + for (Map.Entry entry : paramsMap.entrySet()) { + builder.queryParam(entry.getKey(), entry.getValue()); + } + System.out.println(builder.build(false).encode().toUriString()); + } + + @Test + public void v3Test() { + RestTemplate restTemplate = new RestTemplateBuilder() + .messageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8)) + .build(); + JSONObject params = new JSONObject(); + params.put("client_moniker", "PINE"); + ServerLessFunctionInvokeRequest request = new ServerLessFunctionInvokeRequest(secretId, secretKey, region, function, params); + ResponseEntity resp = restTemplate.exchange(request.request(), String.class); + System.out.println(resp.getBody()); + + } +}