diff --git a/pom.xml b/pom.xml index 4c22babe5..f3c044b2b 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,10 @@ au.com.royalpay.payment rpay-core + + au.com.royalpay.payment + shopify-core + com.github.stuxuhai jpinyin diff --git a/src/main/java/au/com/royalpay/payment/manage/WebConfiguration.java b/src/main/java/au/com/royalpay/payment/manage/WebConfiguration.java index 37eb85115..26d4ad61a 100644 --- a/src/main/java/au/com/royalpay/payment/manage/WebConfiguration.java +++ b/src/main/java/au/com/royalpay/payment/manage/WebConfiguration.java @@ -1,8 +1,6 @@ package au.com.royalpay.payment.manage; import au.com.royalpay.payment.manage.permission.manager.ManagerUserInterceptor; -import au.com.royalpay.payment.manage.shopify.support.ShopifyRequestInfoInterceptor; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -17,16 +15,9 @@ public class WebConfiguration implements WebMvcConfigurer { @Resource private ManagerUserInterceptor managerUserInterceptor; - - @Bean - public ShopifyRequestInfoInterceptor shopifyRequestInfoInterceptor() { - return new ShopifyRequestInfoInterceptor(); - } - @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(managerUserInterceptor).order(1); - registry.addInterceptor(shopifyRequestInfoInterceptor()); } diff --git a/src/main/java/au/com/royalpay/payment/manage/dev/web/TestController.java b/src/main/java/au/com/royalpay/payment/manage/dev/web/TestController.java index d8725038f..2101e2f3c 100644 --- a/src/main/java/au/com/royalpay/payment/manage/dev/web/TestController.java +++ b/src/main/java/au/com/royalpay/payment/manage/dev/web/TestController.java @@ -24,6 +24,7 @@ import au.com.royalpay.payment.manage.merchants.beans.NewSubMerchantIdApply; import au.com.royalpay.payment.manage.merchants.core.ClientManager; import au.com.royalpay.payment.manage.permission.manager.ManagerMapping; import au.com.royalpay.payment.manage.pos.datasource.ReadOnlyConnection; +import au.com.royalpay.payment.manage.shopify.auth.domain.manage.ShopifyManageService; import au.com.royalpay.payment.manage.system.core.TradeSecureService; import au.com.royalpay.payment.manage.tradelog.beans.TradeLogQuery; import au.com.royalpay.payment.manage.tradelog.core.TradeLogService; @@ -66,10 +67,7 @@ import java.io.IOException; import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Optional; +import java.util.*; /** * Created by yixian on 2016-07-06. @@ -131,6 +129,9 @@ public class TestController { @Resource private MerchantChannelApplicationManager merchantChannelApplicationManager; + @Resource + private ShopifyManageService shopifyManageService; + @Resource private AlipayRegisterService alipayRegisterService; @@ -833,4 +834,10 @@ public class TestController { alipayRegisterService.batchUpdateAlipayApply(); } + + @ManagerMapping(value = "/shopify/rotate_secret", method = RequestMethod.POST, role = ManagerRole.DEVELOPER) + public JSONObject rotateShopifySecret(@RequestBody JSONObject rotateRequest) { + List failedStores = shopifyManageService.rotateAccessToken(rotateRequest.getString("secret"), rotateRequest.getString("refresh_token")); + return new JSONObject(Map.of("failed", failedStores)); + } } diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java index 985029eee..c511fd10d 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java @@ -1,12 +1,15 @@ package au.com.royalpay.payment.manage.mappers.shopify; import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; +import com.yixsoft.support.mybatis.autosql.annotations.AdvanceSelect; import com.yixsoft.support.mybatis.autosql.annotations.AutoMapper; import com.yixsoft.support.mybatis.autosql.annotations.AutoSql; import com.yixsoft.support.mybatis.autosql.annotations.SqlType; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; +import java.util.List; + @AutoMapper(tablename = "shopify_store", pkName = "id", keyGenerator = Jdbc3KeyGenerator.class) public interface ShopifyStoreMapper { @@ -18,4 +21,7 @@ public interface ShopifyStoreMapper { @AutoSql(SqlType.UPDATE) void update(ShopifyStore shopifyStore); + + @AdvanceSelect(addonWhereClause = "status=1") + List listAvailableStores(); } diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java index 779b20d90..df0ec94ac 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java @@ -1,9 +1,6 @@ package au.com.royalpay.payment.manage.shopify.auth.domain.application; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyPermissionURL; import au.com.royalpay.payment.manage.shopify.auth.domain.graphqlclient.PaymentsAppConfigureClient; -import au.com.royalpay.payment.manage.shopify.auth.domain.service.ShopifyAuthService; import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyPermissionRequest; import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; import au.com.royalpay.payment.manage.shopify.store.domain.entity.SimpleMerchant; @@ -14,6 +11,10 @@ import au.com.royalpay.payment.manage.shopify.store.domain.service.ShopifyStoreS import au.com.royalpay.payment.manage.signin.beans.LoginInfo; import au.com.royalpay.payment.manage.signin.core.SignInStatusManager; import au.com.royalpay.payment.tools.exceptions.BadRequestException; +import au.com.royalpay.shopify.config.ShopifyAuthProvider; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; +import au.com.royalpay.shopify.entity.ShopifyPermissionURL; +import au.com.royalpay.shopify.service.ShopifyAuthService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -29,9 +30,8 @@ public class ShopifyMerchantAuthApplication { @Value("${shopify.version:2022-01}") private String apiVersion; - @Value("${shopify.auth.apiKey}") - private String apiKey; - + @Autowired + private ShopifyAuthProvider authProvider; private static final String PAYMENT_SETTING_URL = "https://%s/services/payments_partners/gateways/%s/settings"; @Autowired @@ -104,7 +104,7 @@ public class ShopifyMerchantAuthApplication { throw new BadRequestException("Payment app setting error"); } - String redirectUrl = String.format(PAYMENT_SETTING_URL, shop, apiKey); + String redirectUrl = String.format(PAYMENT_SETTING_URL, shop, authProvider.getNewestAuthConfig().getClientId()); return accessToken.setRedirectUrl(redirectUrl); } diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyAccessToken.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyAccessToken.java deleted file mode 100644 index 3e5f7e25d..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyAccessToken.java +++ /dev/null @@ -1,17 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.entity; - -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - -@Data -@Accessors(chain = true) -@NoArgsConstructor -public class ShopifyAccessToken { - - private String access_token; - - private String scope; - - private String redirectUrl; -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyCommonParameter.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyCommonParameter.java deleted file mode 100644 index c5f56f2d0..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyCommonParameter.java +++ /dev/null @@ -1,20 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.entity; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ShopifyCommonParameter { - private String shop; - private String code; - private String state; - private String hmac; - private String host; - private String timestamp; - -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionBackParam.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionBackParam.java deleted file mode 100644 index 034ff1e4c..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionBackParam.java +++ /dev/null @@ -1,18 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.entity; - -import lombok.Data; - -import javax.validation.constraints.NotBlank; - -@Data -public class ShopifyPermissionBackParam { - - @NotBlank(message = "code not blank") - private String code; - private String hmac; - private String host; - @NotBlank(message = "shop not blank") - private String shop; - private String state; - private String timestamp; -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionURL.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionURL.java deleted file mode 100644 index 152161ef1..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionURL.java +++ /dev/null @@ -1,11 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.entity; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class ShopifyPermissionURL { - - private String url; -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/graphqlclient/PaymentsAppConfigureClient.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/graphqlclient/PaymentsAppConfigureClient.java index 943481c20..4acff1ac1 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/graphqlclient/PaymentsAppConfigureClient.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/graphqlclient/PaymentsAppConfigureClient.java @@ -2,7 +2,7 @@ package au.com.royalpay.payment.manage.shopify.auth.domain.graphqlclient; import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; import au.com.royalpay.payment.manage.shopify.store.domain.service.ShopifyStoreService; -import au.com.royalpay.payment.manage.shopify.support.GraphqlSchemaReaderUtil; +import au.com.royalpay.shopify.support.GraphqlSchemaReaderUtil; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/manage/ShopifyManageService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/manage/ShopifyManageService.java new file mode 100644 index 000000000..66d70d98d --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/manage/ShopifyManageService.java @@ -0,0 +1,51 @@ +package au.com.royalpay.payment.manage.shopify.auth.domain.manage; + +import au.com.royalpay.payment.manage.mappers.shopify.ShopifyStoreMapper; +import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; +import au.com.royalpay.shopify.config.ShopifyAuthProvider; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; +import au.com.royalpay.shopify.service.ShopifyAuthService; +import com.alibaba.fastjson.JSONObject; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +public class ShopifyManageService { + + private final ShopifyAuthProvider shopifyAuthProvider; + private final ShopifyAuthService shopifyAuthService; + private final ShopifyStoreMapper shopifyStoreMapper; + + public ShopifyManageService(ShopifyAuthProvider shopifyAuthProvider, ShopifyAuthService shopifyAuthService, ShopifyStoreMapper shopifyStoreMapper) { + this.shopifyAuthProvider = shopifyAuthProvider; + this.shopifyAuthService = shopifyAuthService; + this.shopifyStoreMapper = shopifyStoreMapper; + } + + public List rotateAccessToken(String newSecret, String refreshToken) { + shopifyAuthProvider.addSecret(newSecret); + List failedStore = shopifyStoreMapper.listAvailableStores().parallelStream().filter(store -> !store.getTokenSecret().equalsIgnoreCase(newSecret)) + .map(store -> rotateStoreAccessToken(store, refreshToken)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (failedStore.isEmpty()) { + shopifyAuthProvider.activateSecret(newSecret); + } + return failedStore; + } + + private JSONObject rotateStoreAccessToken(ShopifyStore store, String refreshToken) { + try { + ShopifyAccessToken newToken = shopifyAuthService.rotateAccessToken(store.storeName(), refreshToken, store.getAccessToken()); + shopifyStoreMapper.update(ShopifyStore.builder().id(store.getId()).accessToken(newToken.getAccess_token()).tokenSecret(newToken.getSecret()).build()); + return null; + } catch (Exception e) { + return new JSONObject(Map.of("shop", store.getShopifyShop(), "client_moniker", store.getClientMoniker(), "message", e.getMessage())); + } + + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java deleted file mode 100644 index 56bfbbfb3..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java +++ /dev/null @@ -1,70 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.service; - -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; -import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyAccessTokenRequest; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyPermissionURL; -import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyPermissionRequest; -import au.com.royalpay.payment.tools.env.PlatformEnvironment; -import au.com.royalpay.payment.tools.exceptions.ServerErrorException; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; - -import java.util.Date; - -@Service -@Slf4j -public class ShopifyAuthService { - - @Value("${shopify.auth.apiKey}") - private String clientId; - - @Value("${shopify.auth.apiSecretKey}") - private String clientSecret; - - @Value("${shopify.auth.scope}") - private String scope; - - private static final String PERMISSION_URL = "https://%s/admin/oauth/authorize?client_id=%s&scope=%s&redirect_uri=%s&state=%s&grant_options[]=per-user"; - - private static final String ACCESS_TOKEN_URL = "https://%s/admin/oauth/access_token"; - - @Autowired - @Qualifier("shopifyRestTemplate") - private RestTemplate restTemplate; - - @Autowired - private StringRedisTemplate stringRedisTemplate; - - public ShopifyPermissionURL shopifyPermission(String shopifyStoreHost) { - String redirectUri = PlatformEnvironment.getEnv().concatUrl("/shopify/auth/back"); - - String state = String.valueOf(new Date().getTime()).substring(0,10); - - stringRedisTemplate.boundValueOps("shopifyAuthState:"+shopifyStoreHost).set(state); - - String permissionUrl = String.format(PERMISSION_URL, shopifyStoreHost, clientId, scope, redirectUri, state); - return ShopifyPermissionURL.builder().url(permissionUrl).build(); - } - - public ShopifyAccessToken getAccessToken(String shop, String code) { - ShopifyAccessTokenRequest request = new ShopifyAccessTokenRequest(clientId, clientSecret, code); - ResponseEntity responseEntity; - try { - responseEntity = restTemplate.postForEntity(String.format(ACCESS_TOKEN_URL, shop), request, ShopifyAccessToken.class); - } catch (RestClientException e) { - log.error(String.format("Shopify merchant [%s] get access token error: %s", shop, e.getMessage())); - throw new ServerErrorException(e.getMessage()); - } - ShopifyAccessToken shopifyAccessToken = responseEntity.getBody(); - log.info(String.format("Shopify merchant [%s] access token: %s", shop, shopifyAccessToken)); - return shopifyAccessToken; - } - -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyRequestValidator.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyRequestValidator.java deleted file mode 100644 index 3c7daab6f..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyRequestValidator.java +++ /dev/null @@ -1,31 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.domain.service; - -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyCommonParameter; -import au.com.royalpay.payment.manage.shopify.support.HmacVerificationUtil; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -public class ShopifyRequestValidator { - - @Value("${shopify.auth.apiSecretKey}") - private String clientSecret; - - public Boolean valid(ShopifyCommonParameter parameter) { - StringBuilder message = new StringBuilder(); - message.append("code=").append(parameter.getCode()) - .append("&host=").append(parameter.getHost()) - .append("&shop=").append(parameter.getShop()) - .append("&state=").append(parameter.getState()) - .append("×tamp=").append(parameter.getTimestamp()); - return HmacVerificationUtil.hmacSHA256(message.toString(), clientSecret, parameter.getHmac()); - } - - public boolean verifyPermission(String queryStrWithoutHmac, String hmac) { - return HmacVerificationUtil.hmacSHA256(queryStrWithoutHmac, clientSecret, hmac); - } - - public boolean verify(String message, String hmac) { - return HmacVerificationUtil.hmacSHA256(message, clientSecret, hmac); - } -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java index 745dff1f6..572be4987 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java @@ -1,8 +1,8 @@ package au.com.royalpay.payment.manage.shopify.auth.web; import au.com.royalpay.payment.manage.shopify.auth.domain.application.ShopifyMerchantAuthApplication; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyPermissionRequest; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthTemplateController.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthTemplateController.java index c3b210ec3..1d6fd77bc 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthTemplateController.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthTemplateController.java @@ -1,13 +1,13 @@ package au.com.royalpay.payment.manage.shopify.auth.web; import au.com.royalpay.payment.manage.shopify.auth.domain.application.ShopifyMerchantAuthApplication; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyCommonParameter; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyPermissionURL; import au.com.royalpay.payment.manage.shopify.auth.domain.exception.ShopifyRequestVerifyException; -import au.com.royalpay.payment.manage.shopify.auth.domain.service.ShopifyRequestValidator; -import au.com.royalpay.payment.manage.shopify.support.ShopifyEndpoint; import au.com.royalpay.payment.tools.env.PlatformEnvironment; import au.com.royalpay.payment.tools.exceptions.BadRequestException; +import au.com.royalpay.shopify.entity.ShopifyCommonParameter; +import au.com.royalpay.shopify.entity.ShopifyPermissionURL; +import au.com.royalpay.shopify.service.ShopifyRequestValidator; +import au.com.royalpay.shopify.support.ShopifyEndpoint; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyAccessTokenRequest.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyAccessTokenRequest.java deleted file mode 100644 index 3343a225e..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyAccessTokenRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.auth.web.command; - -import lombok.Data; - -@Data -public class ShopifyAccessTokenRequest { - - private String client_id; - private String client_secret; - private String code; - - public ShopifyAccessTokenRequest(String clientId, String clientSecret, String code) { - this.client_id = clientId; - this.client_secret = clientSecret; - this.code = code; - } -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/config/ShopifyApplicationConfig.java b/src/main/java/au/com/royalpay/payment/manage/shopify/config/ShopifyApplicationConfig.java deleted file mode 100644 index 173b1d53f..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/config/ShopifyApplicationConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.config; - -import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; -import com.google.common.collect.ImmutableList; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.http.converter.ByteArrayHttpMessageConverter; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.web.client.RestTemplate; - -import java.nio.charset.StandardCharsets; - -@Configuration -public class ShopifyApplicationConfig { - - @Bean - @Qualifier("shopifyRestTemplate") - public RestTemplate restTemplate() { - FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); - fastJsonHttpMessageConverter.setSupportedMediaTypes(ImmutableList.of(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)); - return new RestTemplateBuilder() - .messageConverters(new ByteArrayHttpMessageConverter(), - new StringHttpMessageConverter(StandardCharsets.UTF_8), - fastJsonHttpMessageConverter) - .build(); - } -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/hooks/ShopifyWebhooksController.java b/src/main/java/au/com/royalpay/payment/manage/shopify/hooks/ShopifyWebhooksController.java index 8145a3407..e5a6bfc65 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/hooks/ShopifyWebhooksController.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/hooks/ShopifyWebhooksController.java @@ -1,14 +1,14 @@ package au.com.royalpay.payment.manage.shopify.hooks; import au.com.royalpay.payment.manage.shopify.auth.domain.exception.ShopifyRequestVerifyException; -import au.com.royalpay.payment.manage.shopify.auth.domain.service.ShopifyRequestValidator; import au.com.royalpay.payment.manage.shopify.hooks.command.ShopifyCustomerRedactCommand; import au.com.royalpay.payment.manage.shopify.hooks.command.ShopifyCustomerRequestCommand; import au.com.royalpay.payment.manage.shopify.hooks.command.ShopifyShopRedactCommand; import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; import au.com.royalpay.payment.manage.shopify.store.domain.service.ShopifyStoreService; -import au.com.royalpay.payment.manage.shopify.support.ShopifyEndpoint; -import au.com.royalpay.payment.manage.shopify.support.ShopifyHttpUtils; +import au.com.royalpay.shopify.service.ShopifyRequestValidator; +import au.com.royalpay.shopify.support.ShopifyEndpoint; +import au.com.royalpay.shopify.support.ShopifyHttpUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/application/ShopifyStoreApplication.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/application/ShopifyStoreApplication.java index 29a063e1a..5a21426c5 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/application/ShopifyStoreApplication.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/application/ShopifyStoreApplication.java @@ -1,7 +1,6 @@ package au.com.royalpay.payment.manage.shopify.store.domain.application; import au.com.royalpay.payment.manage.shopify.auth.domain.application.ShopifyMerchantAuthApplication; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyPermissionRequest; import au.com.royalpay.payment.manage.shopify.store.domain.context.MerchantCreateContext; import au.com.royalpay.payment.manage.shopify.store.domain.entity.MerchantAccountRequest; @@ -11,6 +10,7 @@ import au.com.royalpay.payment.manage.shopify.store.domain.service.MerchantAccou import au.com.royalpay.payment.manage.shopify.store.domain.service.MerchantService; import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand; import au.com.royalpay.payment.manage.shopify.support.PlatformMerchantProvider; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java index 154730cfe..0969060d0 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java @@ -1,6 +1,6 @@ package au.com.royalpay.payment.manage.shopify.store.domain.entity; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -9,6 +9,8 @@ import lombok.experimental.Accessors; import java.util.Date; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Data @Builder @@ -35,6 +37,8 @@ public class ShopifyStore { private String accessToken; + private String tokenSecret; + private String scope; private int status; @@ -48,7 +52,18 @@ public class ShopifyStore { .createTime(new Date()) .creator("shopify store") .accessToken(accessToken.getAccess_token()) + .tokenSecret(accessToken.getSecret()) .scope(accessToken.getScope()) - .modifyTime(new Date()).build(); + .modifyTime(new Date()) + .status(1).build(); + } + + public String storeName(){ + Pattern pattern = Pattern.compile("(^[a-zA-Z0-9][a-zA-Z0-9\\-]*)\\.myshopify\\.com"); + Matcher matcher = pattern.matcher(shopifyShop); + if (matcher.matches()){ + return matcher.group(1); + } + return shopifyShop; } } diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java index 48806bc51..e12817847 100644 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java @@ -1,8 +1,8 @@ package au.com.royalpay.payment.manage.shopify.store.web; -import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken; import au.com.royalpay.payment.manage.shopify.store.domain.application.ShopifyStoreApplication; import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand; +import au.com.royalpay.shopify.entity.ShopifyAccessToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/GraphqlSchemaReaderUtil.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/GraphqlSchemaReaderUtil.java deleted file mode 100644 index 6fdfe7c21..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/GraphqlSchemaReaderUtil.java +++ /dev/null @@ -1,11 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import java.io.IOException; - -public class GraphqlSchemaReaderUtil { - - public static String getSchemaFromFileName(final String filename) throws IOException { - return new String( - GraphqlSchemaReaderUtil.class.getClassLoader().getResourceAsStream("graphql/" + filename + ".graphql").readAllBytes()); - } -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtil.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtil.java deleted file mode 100644 index 992b0252e..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtil.java +++ /dev/null @@ -1,75 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.codec.digest.HmacAlgorithms; -import org.apache.commons.codec.digest.HmacUtils; -import org.apache.commons.lang3.StringUtils; -import org.bouncycastle.crypto.RuntimeCryptoException; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.bind.annotation.adapters.HexBinaryAdapter; -import java.nio.charset.StandardCharsets; -import java.security.Security; -import java.util.Arrays; -import java.util.Locale; - -public class HmacVerificationUtil { - private static final Logger logger = LoggerFactory.getLogger(HmacVerificationUtil.class); - - private HmacVerificationUtil() { - } - - public static boolean checkParameters(String message, String secret, String hmac) { - try { - Security.addProvider(new BouncyCastleProvider()); - SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); - Mac mac = Mac.getInstance(secretKey.getAlgorithm()); - mac.init(secretKey); - byte[] digest = mac.doFinal(message.getBytes(StandardCharsets.UTF_8)); - String marshal = new HexBinaryAdapter().marshal(digest).toLowerCase(Locale.ROOT); - return StringUtils.equals(marshal, hmac); - } catch (Exception e) { - throw new RuntimeCryptoException("加密异常"); - } - } - - public static boolean hmacSHA256(String input, String key, String hmac) { - if (isHex(hmac)) { - try { - byte[] requestHmac = Hex.decodeHex(hmac); - byte[] hmacRes = hmac(input, key, HmacAlgorithms.HMAC_SHA_256); - String hmacHex = Hex.encodeHexString(hmacRes); - logger.debug("hex-mode: input={}; key={}; encoded={}; request-hmac: {}", input, key, hmacHex, hmac); - return Arrays.equals(requestHmac, hmacRes); - } catch (DecoderException ignore) { - return false; - } - } else { - //base64 - byte[] hmacRes = hmac(input, key, HmacAlgorithms.HMAC_SHA_256); - String hmacB64 = Base64.encodeBase64String(hmacRes); - logger.debug("b64-mode: input={}; key={}; encoded={}; request-hmac: {}", input, key, hmacB64, hmac); - byte[] requestHmac = Base64.decodeBase64(hmac); - return Arrays.equals(requestHmac, hmacRes); - } - } - - private static boolean isHex(String str) { - return str != null && str.toUpperCase(Locale.ROOT).matches("^[0-9A-F]+$"); - } - - private static byte[] hmac(String input, String key, HmacAlgorithms algorithm) { - Mac mac = HmacUtils.getInitializedMac(algorithm, key.getBytes(StandardCharsets.UTF_8)); - byte[] content = input.getBytes(StandardCharsets.UTF_8); - return mac.doFinal(content); - } - - -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyEndpoint.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyEndpoint.java deleted file mode 100644 index f80fd004b..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyEndpoint.java +++ /dev/null @@ -1,9 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import java.lang.annotation.*; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface ShopifyEndpoint { -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyHttpUtils.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyHttpUtils.java deleted file mode 100644 index dc48f240f..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyHttpUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import au.com.royalpay.payment.tools.exceptions.ServerErrorException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StreamUtils; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -public class ShopifyHttpUtils { - private ShopifyHttpUtils() { - } - - private static final Logger logger = LoggerFactory.getLogger(ShopifyHttpUtils.class); - - public static String getRequestBody(HttpServletRequest request) { - try (InputStream in = request.getInputStream()) { - String body = StreamUtils.copyToString(in, StandardCharsets.UTF_8); - logger.debug("Shopify read body |-{}", body); - return body; - } catch (IOException e) { - throw new ServerErrorException("Failed to read request content"); - } - } -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyRequestInfoInterceptor.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyRequestInfoInterceptor.java deleted file mode 100644 index fc9934f1b..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/ShopifyRequestInfoInterceptor.java +++ /dev/null @@ -1,51 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import com.alibaba.fastjson.JSON; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.http.HttpMethod; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; -import java.util.Optional; - -public class ShopifyRequestInfoInterceptor extends HandlerInterceptorAdapter { - private Logger logger = LoggerFactory.getLogger(getClass()); - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if (!(handler instanceof HandlerMethod)){ - return super.preHandle(request, response, handler); - } - Method method = ((HandlerMethod) handler).getMethod(); - - if(HttpMethod.GET.matches(request.getMethod())) { - if (AnnotatedElementUtils.isAnnotated(method, ShopifyEndpoint.class)) { - String shop = request.getParameter("shop"); - if (StringUtils.isNotBlank(shop)) { - response.addHeader("Content-Security-Policy", "frame-ancestors 'none'"); - } - } - } - - if (HttpMethod.POST.matches(request.getMethod())) { - if (AnnotatedElementUtils.isAnnotated(method, ShopifyEndpoint.class)) { - - String requestBody = ShopifyHttpUtils.getRequestBody(request); - logger.debug("shopify request body:[POST]{} -->{}", request.getRequestURI(), requestBody); - String shop = Optional.ofNullable(requestBody).map(JSON::parseObject).map(body->body.getString("shop_domain")).orElse(null); - if (StringUtils.isNotBlank(shop)) { - response.addHeader("Content-Security-Policy", "frame-ancestors 'none'"); - } - } - } - - return super.preHandle(request, response, handler); - } - -} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/support/SpringContextUtil.java b/src/main/java/au/com/royalpay/payment/manage/shopify/support/SpringContextUtil.java deleted file mode 100644 index a1ded1209..000000000 --- a/src/main/java/au/com/royalpay/payment/manage/shopify/support/SpringContextUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -package au.com.royalpay.payment.manage.shopify.support; - -import org.apache.poi.ss.formula.functions.T; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; - -public class SpringContextUtil { - - // Spring应用上下文环境 - private static ApplicationContext applicationContext; - - /** - * 实现ApplicationContextAware接口的回调方法,设置上下文环境 - */ - public static void setApplicationContext(ApplicationContext applicationContext)throws BeansException { - SpringContextUtil.applicationContext = applicationContext; - } - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - /** - * 根据beanId返回Spring中的实例 - * @Date 2019-08-07 17:36 - * @param - * @return - **/ - public static Object getBean(String beanId) throws BeansException { - return applicationContext.getBean(beanId); - } - - public static Object getBean(Class className) { - return applicationContext.getBean(className); - } - -} diff --git a/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStoreTest.java b/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStoreTest.java new file mode 100644 index 000000000..100441250 --- /dev/null +++ b/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStoreTest.java @@ -0,0 +1,17 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.entity; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ShopifyStoreTest { + + @Test + void storeName() { + ShopifyStore store = ShopifyStore.builder() + .shopifyShop("test-store-nicks-4.myshopify.com") + .build(); + Assertions.assertEquals(store.storeName(), "test-store-nicks-4", "storename match"); + } +} \ No newline at end of file diff --git a/src/test/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtilTest.java b/src/test/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtilTest.java index acc19713a..2ee38b24e 100644 --- a/src/test/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtilTest.java +++ b/src/test/java/au/com/royalpay/payment/manage/shopify/support/HmacVerificationUtilTest.java @@ -1,5 +1,6 @@ package au.com.royalpay.payment.manage.shopify.support; +import au.com.royalpay.shopify.support.HmacVerificationUtil; import org.junit.jupiter.api.Test; import org.springframework.web.util.UriComponentsBuilder;