Merge remote-tracking branch 'origin/develop' into develop

master
dalong306 3 years ago
commit 95ef1d2ff2

@ -43,6 +43,10 @@
<groupId>au.com.royalpay.payment</groupId> <groupId>au.com.royalpay.payment</groupId>
<artifactId>rpay-core</artifactId> <artifactId>rpay-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>au.com.royalpay.payment</groupId>
<artifactId>shopify-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.github.stuxuhai</groupId> <groupId>com.github.stuxuhai</groupId>
<artifactId>jpinyin</artifactId> <artifactId>jpinyin</artifactId>

@ -1,8 +1,6 @@
package au.com.royalpay.payment.manage; package au.com.royalpay.payment.manage;
import au.com.royalpay.payment.manage.permission.manager.ManagerUserInterceptor; 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.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -17,16 +15,9 @@ public class WebConfiguration implements WebMvcConfigurer {
@Resource @Resource
private ManagerUserInterceptor managerUserInterceptor; private ManagerUserInterceptor managerUserInterceptor;
@Bean
public ShopifyRequestInfoInterceptor shopifyRequestInfoInterceptor() {
return new ShopifyRequestInfoInterceptor();
}
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(managerUserInterceptor).order(1); registry.addInterceptor(managerUserInterceptor).order(1);
registry.addInterceptor(shopifyRequestInfoInterceptor());
} }

@ -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.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping; import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.pos.datasource.ReadOnlyConnection; 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.system.core.TradeSecureService;
import au.com.royalpay.payment.manage.tradelog.beans.TradeLogQuery; import au.com.royalpay.payment.manage.tradelog.beans.TradeLogQuery;
import au.com.royalpay.payment.manage.tradelog.core.TradeLogService; import au.com.royalpay.payment.manage.tradelog.core.TradeLogService;
@ -66,10 +67,7 @@ import java.io.IOException;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Optional;
/** /**
* Created by yixian on 2016-07-06. * Created by yixian on 2016-07-06.
@ -131,6 +129,9 @@ public class TestController {
@Resource @Resource
private MerchantChannelApplicationManager merchantChannelApplicationManager; private MerchantChannelApplicationManager merchantChannelApplicationManager;
@Resource
private ShopifyManageService shopifyManageService;
@Resource @Resource
private AlipayRegisterService alipayRegisterService; private AlipayRegisterService alipayRegisterService;
@ -833,4 +834,10 @@ public class TestController {
alipayRegisterService.batchUpdateAlipayApply(); alipayRegisterService.batchUpdateAlipayApply();
} }
@ManagerMapping(value = "/shopify/rotate_secret", method = RequestMethod.POST, role = ManagerRole.DEVELOPER)
public JSONObject rotateShopifySecret(@RequestBody JSONObject rotateRequest) {
List<JSONObject> failedStores = shopifyManageService.rotateAccessToken(rotateRequest.getString("secret"), rotateRequest.getString("refresh_token"));
return new JSONObject(Map.of("failed", failedStores));
}
} }

@ -1,12 +1,15 @@
package au.com.royalpay.payment.manage.mappers.shopify; package au.com.royalpay.payment.manage.mappers.shopify;
import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; 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.AutoMapper;
import com.yixsoft.support.mybatis.autosql.annotations.AutoSql; import com.yixsoft.support.mybatis.autosql.annotations.AutoSql;
import com.yixsoft.support.mybatis.autosql.annotations.SqlType; import com.yixsoft.support.mybatis.autosql.annotations.SqlType;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import java.util.List;
@AutoMapper(tablename = "shopify_store", pkName = "id", keyGenerator = Jdbc3KeyGenerator.class) @AutoMapper(tablename = "shopify_store", pkName = "id", keyGenerator = Jdbc3KeyGenerator.class)
public interface ShopifyStoreMapper { public interface ShopifyStoreMapper {
@ -18,4 +21,7 @@ public interface ShopifyStoreMapper {
@AutoSql(SqlType.UPDATE) @AutoSql(SqlType.UPDATE)
void update(ShopifyStore shopifyStore); void update(ShopifyStore shopifyStore);
@AdvanceSelect(addonWhereClause = "status=1")
List<ShopifyStore> listAvailableStores();
} }

@ -1,9 +1,6 @@
package au.com.royalpay.payment.manage.shopify.auth.domain.application; 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.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.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.ShopifyStore;
import au.com.royalpay.payment.manage.shopify.store.domain.entity.SimpleMerchant; 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.beans.LoginInfo;
import au.com.royalpay.payment.manage.signin.core.SignInStatusManager; import au.com.royalpay.payment.manage.signin.core.SignInStatusManager;
import au.com.royalpay.payment.tools.exceptions.BadRequestException; 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -29,9 +30,8 @@ public class ShopifyMerchantAuthApplication {
@Value("${shopify.version:2022-01}") @Value("${shopify.version:2022-01}")
private String apiVersion; private String apiVersion;
@Value("${shopify.auth.apiKey}") @Autowired
private String apiKey; private ShopifyAuthProvider authProvider;
private static final String PAYMENT_SETTING_URL = "https://%s/services/payments_partners/gateways/%s/settings"; private static final String PAYMENT_SETTING_URL = "https://%s/services/payments_partners/gateways/%s/settings";
@Autowired @Autowired
@ -104,7 +104,7 @@ public class ShopifyMerchantAuthApplication {
throw new BadRequestException("Payment app setting error"); 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); return accessToken.setRedirectUrl(redirectUrl);
} }

@ -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;
}

@ -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;
}

@ -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;
}

@ -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;
}

@ -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.entity.ShopifyStore;
import au.com.royalpay.payment.manage.shopify.store.domain.service.ShopifyStoreService; 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 com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

@ -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<JSONObject> rotateAccessToken(String newSecret, String refreshToken) {
shopifyAuthProvider.addSecret(newSecret);
List<JSONObject> 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()));
}
}
}

@ -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<ShopifyAccessToken> 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;
}
}

@ -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("&timestamp=").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);
}
}

@ -1,8 +1,8 @@
package au.com.royalpay.payment.manage.shopify.auth.web; 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.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.auth.web.command.ShopifyPermissionRequest;
import au.com.royalpay.shopify.entity.ShopifyAccessToken;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;

@ -1,13 +1,13 @@
package au.com.royalpay.payment.manage.shopify.auth.web; 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.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.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.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.exceptions.BadRequestException; 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.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;

@ -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;
}
}

@ -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();
}
}

@ -1,14 +1,14 @@
package au.com.royalpay.payment.manage.shopify.hooks; 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.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.ShopifyCustomerRedactCommand;
import au.com.royalpay.payment.manage.shopify.hooks.command.ShopifyCustomerRequestCommand; 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.hooks.command.ShopifyShopRedactCommand;
import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; 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.store.domain.service.ShopifyStoreService;
import au.com.royalpay.payment.manage.shopify.support.ShopifyEndpoint; import au.com.royalpay.shopify.service.ShopifyRequestValidator;
import au.com.royalpay.payment.manage.shopify.support.ShopifyHttpUtils; import au.com.royalpay.shopify.support.ShopifyEndpoint;
import au.com.royalpay.shopify.support.ShopifyHttpUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;

@ -1,7 +1,6 @@
package au.com.royalpay.payment.manage.shopify.store.domain.application; 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.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.auth.web.command.ShopifyPermissionRequest;
import au.com.royalpay.payment.manage.shopify.store.domain.context.MerchantCreateContext; import au.com.royalpay.payment.manage.shopify.store.domain.context.MerchantCreateContext;
import au.com.royalpay.payment.manage.shopify.store.domain.entity.MerchantAccountRequest; 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.domain.service.MerchantService;
import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand; import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand;
import au.com.royalpay.payment.manage.shopify.support.PlatformMerchantProvider; 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.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationEventPublisherAware;

@ -1,6 +1,6 @@
package au.com.royalpay.payment.manage.shopify.store.domain.entity; 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.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -9,6 +9,8 @@ import lombok.experimental.Accessors;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data @Data
@Builder @Builder
@ -35,6 +37,8 @@ public class ShopifyStore {
private String accessToken; private String accessToken;
private String tokenSecret;
private String scope; private String scope;
private int status; private int status;
@ -48,7 +52,18 @@ public class ShopifyStore {
.createTime(new Date()) .createTime(new Date())
.creator("shopify store") .creator("shopify store")
.accessToken(accessToken.getAccess_token()) .accessToken(accessToken.getAccess_token())
.tokenSecret(accessToken.getSecret())
.scope(accessToken.getScope()) .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;
} }
} }

@ -1,8 +1,8 @@
package au.com.royalpay.payment.manage.shopify.store.web; 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.domain.application.ShopifyStoreApplication;
import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand; 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.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;

@ -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());
}
}

@ -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);
}
}

@ -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 {
}

@ -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");
}
}
}

@ -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);
}
}

@ -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;
}
/**
* beanIdSpring
* @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<T> className) {
return applicationContext.getBean(className);
}
}

@ -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");
}
}

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.shopify.support; package au.com.royalpay.payment.manage.shopify.support;
import au.com.royalpay.shopify.support.HmacVerificationUtil;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;

Loading…
Cancel
Save