From f441fe9b5e86a1211a7ef55c39c65f0de358e84a Mon Sep 17 00:00:00 2001 From: ycfxx Date: Thu, 23 Dec 2021 10:52:40 +0800 Subject: [PATCH] upgrade add shopify auth --- .../mappers/shopify/ShopifyStoreMapper.java | 18 +++ .../manage/mappers/system/MerchantMapper.java | 15 ++ .../ShopifyMerchantAuthApplication.java | 66 +++++++++ .../domain/entity/ShopifyAccessToken.java | 11 ++ .../entity/ShopifyPermissionBackParam.java | 18 +++ .../domain/entity/ShopifyPermissionURL.java | 11 ++ .../domain/service/ShopifyAuthService.java | 60 ++++++++ .../auth/web/ShopifyAuthController.java | 53 +++++++ .../command/ShopifyAccessTokenRequest.java | 17 +++ .../web/command/ShopifyPermissionRequest.java | 18 +++ .../config/ShopifyApplicationConfig.java | 30 ++++ .../store/domain/entity/ShopifyStore.java | 46 ++++++ .../store/domain/service/MerchantService.java | 21 +++ .../service/PaymentAppMerchantService.java | 21 +++ .../domain/service/ShopifyStoreService.java | 21 +++ .../service/impl/ShopifyStoreServiceImpl.java | 24 ++++ .../store/web/ShopifyStoreController.java | 29 ++++ src/main/resources/application-dev.yml | 2 +- src/main/resources/application.yml | 6 + .../templates/shopify/auth_back.html | 10 ++ src/main/ui/auth.html | 131 ++++++++++++++++++ src/main/ui/static/boot/shopify-auth-boot.js | 80 +++++++++++ src/main/ui/static/boot/shopifyMainApp.js | 27 ++++ .../static/shopify/auth/shopify.auth.back.js | 32 +++++ .../ui/static/shopify/auth/shopify.auth.js | 67 +++++++++ .../shopify/auth/templates/auth_root.html | 40 ++++++ .../shopify/auth/templates/shopify_auth.html | 42 ++++++ .../auth/templates/shopify_auth_back.html | 14 ++ .../shopify/auth/templates/shopify_login.html | 54 ++++++++ .../auth/templates/shopify_register.html | 31 +++++ .../service/ShopifyStoreServiceTest.java | 44 ++++++ 31 files changed, 1058 insertions(+), 1 deletion(-) create mode 100644 src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/mappers/system/MerchantMapper.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyAccessToken.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionBackParam.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionURL.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyAccessTokenRequest.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyPermissionRequest.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/config/ShopifyApplicationConfig.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/MerchantService.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/PaymentAppMerchantService.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreService.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/impl/ShopifyStoreServiceImpl.java create mode 100644 src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java create mode 100644 src/main/resources/templates/shopify/auth_back.html create mode 100644 src/main/ui/auth.html create mode 100644 src/main/ui/static/boot/shopify-auth-boot.js create mode 100644 src/main/ui/static/boot/shopifyMainApp.js create mode 100644 src/main/ui/static/shopify/auth/shopify.auth.back.js create mode 100644 src/main/ui/static/shopify/auth/shopify.auth.js create mode 100644 src/main/ui/static/shopify/auth/templates/auth_root.html create mode 100644 src/main/ui/static/shopify/auth/templates/shopify_auth.html create mode 100644 src/main/ui/static/shopify/auth/templates/shopify_auth_back.html create mode 100644 src/main/ui/static/shopify/auth/templates/shopify_login.html create mode 100644 src/main/ui/static/shopify/auth/templates/shopify_register.html create mode 100644 src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreServiceTest.java 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 new file mode 100644 index 000000000..c18a3028c --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/shopify/ShopifyStoreMapper.java @@ -0,0 +1,18 @@ +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.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; + +@AutoMapper(tablename = "shopify_store", pkName = "id", keyGenerator = Jdbc3KeyGenerator.class) +public interface ShopifyStoreMapper { + + @AutoSql(SqlType.INSERT) + void insert(ShopifyStore shopifyStore); + + @AutoSql(SqlType.SELECT) + ShopifyStore selectByShop(@Param("shopify_shop") String shop); +} diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/system/MerchantMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/system/MerchantMapper.java new file mode 100644 index 000000000..96c847260 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/system/MerchantMapper.java @@ -0,0 +1,15 @@ +package au.com.royalpay.payment.manage.mappers.system; + +import com.alibaba.fastjson.JSONObject; +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; + +@AutoMapper(tablename = "sys_clients", pkName = "client_id", keyGenerator = Jdbc3KeyGenerator.class) +public interface MerchantMapper { + + @AutoSql(SqlType.SELECT) + public JSONObject selectByLoginId(@Param("client_id") String loginId); +} 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 new file mode 100644 index 000000000..93ca14369 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/application/ShopifyMerchantAuthApplication.java @@ -0,0 +1,66 @@ +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.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.service.ShopifyStoreService; +import au.com.royalpay.payment.manage.signin.beans.LoginInfo; +import au.com.royalpay.payment.manage.signin.core.SignInAccountService; +import au.com.royalpay.payment.manage.signin.core.SignInStatusManager; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +@Component +public class ShopifyMerchantAuthApplication { + + private static final String redisPrefix = "shopify:accessToken:%s"; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private ShopifyAuthService shopifyAuthService; + + @Autowired + private ShopifyStoreService shopifyStoreService; + + @Autowired + private SignInAccountService signInAccountService; + + @Autowired + private SignInStatusManager signInStatusManager; + + /** + * 获取shopify店铺授权URL + * + * @param request 店铺信息 + * @return + */ + public ShopifyPermissionURL shopifyPermission(ShopifyPermissionRequest request) { + LoginInfo loginInfo = new LoginInfo(); + loginInfo.setLoginId(request.getLoginId()); + loginInfo.setPassword(request.getPassword()); + String statusKey = signInStatusManager.partnerSignIn(loginInfo); + JSONObject client = signInStatusManager.getCurrentClient(statusKey); + + shopifyStoreService.createShopifyStore(ShopifyStore.instanceOf(client, request.getShop())); + return shopifyAuthService.shopifyPermission(request); + } + + /** + * shopify商户授权 + * + * @param shop shopify商户标识 + * @param code 授权code + * @return + */ + public ShopifyAccessToken merchantOnboard(String shop, String code) { + ShopifyAccessToken accessToken = shopifyAuthService.getAccessToken(shop, code); + redisTemplate.boundValueOps(String.format(redisPrefix, shop)).set(accessToken.getAccess_token()); + return accessToken; + } +} 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 new file mode 100644 index 000000000..a28858350 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyAccessToken.java @@ -0,0 +1,11 @@ +package au.com.royalpay.payment.manage.shopify.auth.domain.entity; + +import lombok.Data; + +@Data +public class ShopifyAccessToken { + + private String access_token; + + private String scope; +} 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 new file mode 100644 index 000000000..034ff1e4c --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionBackParam.java @@ -0,0 +1,18 @@ +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 new file mode 100644 index 000000000..152161ef1 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/entity/ShopifyPermissionURL.java @@ -0,0 +1,11 @@ +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/service/ShopifyAuthService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java new file mode 100644 index 000000000..1f88d2384 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/domain/service/ShopifyAuthService.java @@ -0,0 +1,60 @@ +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.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; + + public ShopifyPermissionURL shopifyPermission(ShopifyPermissionRequest request) { + String redirectUri = PlatformEnvironment.getEnv().concatUrl("/shopify/auth/back"); + String permissionUrl = String.format(PERMISSION_URL, request.getShop(), clientId, scope, redirectUri, String.valueOf(new Date().getTime()).substring(0,10)); + 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/web/ShopifyAuthController.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java new file mode 100644 index 000000000..6599ccb05 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/ShopifyAuthController.java @@ -0,0 +1,53 @@ +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.domain.entity.ShopifyPermissionURL; +import au.com.royalpay.payment.manage.shopify.auth.web.command.ShopifyPermissionRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.validation.Valid; + +/** + * shopify认证授权资源 + */ +@RestController +@RequestMapping(value = "/shopify/auth") +public class ShopifyAuthController { + + @Autowired + private ShopifyMerchantAuthApplication shopifyMerchantAuthApplication; + + /** + * 获取shopify店铺授权URL + * + * @param request 店铺信息 + * @return + */ + @PostMapping("/permission") + public ShopifyPermissionURL shopifyPermission(@RequestBody @Valid ShopifyPermissionRequest request) { + ShopifyPermissionURL shopifyPermissionURL = shopifyMerchantAuthApplication.shopifyPermission(request); + return shopifyPermissionURL; + } + + /** + * shopify授权回调接口 + * + * @return + */ + @GetMapping("/back") + public ModelAndView shopifyAuthBack(@RequestParam(value = "code") String code, + @RequestParam(name = "hmac", required = false) String hmac, + @RequestParam(name = "host", required = false) String host, + @RequestParam("shop") String shop, + @RequestParam(name = "state", required = false) String state, + @RequestParam(name = "timestamp", required = false) String timestamp) { + ShopifyAccessToken accessToken = shopifyMerchantAuthApplication.merchantOnboard(shop, code); + ModelAndView view = new ModelAndView("shopify/auth_back"); + view.addObject("accessToken",accessToken); + return view; + } + +} 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 new file mode 100644 index 000000000..3343a225e --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyAccessTokenRequest.java @@ -0,0 +1,17 @@ +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/auth/web/command/ShopifyPermissionRequest.java b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyPermissionRequest.java new file mode 100644 index 000000000..494f17fca --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/auth/web/command/ShopifyPermissionRequest.java @@ -0,0 +1,18 @@ +package au.com.royalpay.payment.manage.shopify.auth.web.command; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class ShopifyPermissionRequest { + + @NotBlank(message = "Shop can not blank") + private String shop; + + @NotBlank(message = "Login Id can not blank") + private String loginId; + + @NotBlank(message = "Password can not blank") + private String password; +} 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 new file mode 100644 index 000000000..173b1d53f --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/config/ShopifyApplicationConfig.java @@ -0,0 +1,30 @@ +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/store/domain/entity/ShopifyStore.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java new file mode 100644 index 000000000..de6e6bba7 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/entity/ShopifyStore.java @@ -0,0 +1,46 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.entity; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.UUID; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ShopifyStore { + + private String id; + + private Integer clientId; + + private String clientMoniker; + + private String shopifyShop; + + private Date createTime; + + private String creator; + + private Date modifyTime; + + private String modifier; + + public static ShopifyStore instanceOf(JSONObject client, String shop) { + Integer clientId = client.getInteger("client_id"); + String clientMoniker = client.getString("client_moniker"); + return ShopifyStore.builder() + .id(UUID.randomUUID().toString()) + .clientId(clientId) + .clientMoniker(clientMoniker) + .shopifyShop(shop) + .createTime(new Date()) + .creator("shopify") + .modifyTime(new Date()).build(); + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/MerchantService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/MerchantService.java new file mode 100644 index 000000000..b7529fa43 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/MerchantService.java @@ -0,0 +1,21 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.service; + +import au.com.royalpay.payment.manage.mappers.system.ClientAccountMapper; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MerchantService { + + @Autowired + private ClientAccountMapper clientAccountMapper; + + public Boolean existMerchant(String loginId) { + JSONObject account = clientAccountMapper.findByUsername(loginId); + if (account == null) { + return false; + } + return true; + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/PaymentAppMerchantService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/PaymentAppMerchantService.java new file mode 100644 index 000000000..6ec1a0255 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/PaymentAppMerchantService.java @@ -0,0 +1,21 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class PaymentAppMerchantService { + + @Autowired + private MerchantService merchantservice; + + /** + * 检查loginId的商户是否存在 + * + * @param loginId 商户用户标识 + * @return + */ + public Boolean existMerchant(String loginId) { + return merchantservice.existMerchant(loginId); + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreService.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreService.java new file mode 100644 index 000000000..55441447d --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreService.java @@ -0,0 +1,21 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.service; + +import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; + +public interface ShopifyStoreService { + + /** + * 关联shopify店铺 + * + * @param shopifyStore 店铺信息 + */ + void createShopifyStore(ShopifyStore shopifyStore); + + /** + * 根据shop获取shopify store + * + * @param shop 店铺标识 + * @return + */ + ShopifyStore getByShopifyShop(String shop); +} diff --git a/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/impl/ShopifyStoreServiceImpl.java b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/impl/ShopifyStoreServiceImpl.java new file mode 100644 index 000000000..0d0ccd75a --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/domain/service/impl/ShopifyStoreServiceImpl.java @@ -0,0 +1,24 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.service.impl; + +import au.com.royalpay.payment.manage.mappers.shopify.ShopifyStoreMapper; +import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; +import au.com.royalpay.payment.manage.shopify.store.domain.service.ShopifyStoreService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ShopifyStoreServiceImpl implements ShopifyStoreService { + + @Autowired + private ShopifyStoreMapper shopifyStoreMapper; + + @Override + public void createShopifyStore(ShopifyStore shopifyStore) { + shopifyStoreMapper.insert(shopifyStore); + } + + @Override + public ShopifyStore getByShopifyShop(String shop) { + return shopifyStoreMapper.selectByShop(shop); + } +} 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 new file mode 100644 index 000000000..76813b27a --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/shopify/store/web/ShopifyStoreController.java @@ -0,0 +1,29 @@ +package au.com.royalpay.payment.manage.shopify.store.web; + +import au.com.royalpay.payment.manage.shopify.store.domain.service.PaymentAppMerchantService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * shopify店铺资源 + */ +@RestController +@RequestMapping(value = "/shopify/store") +public class ShopifyStoreController { + + @Autowired + private PaymentAppMerchantService paymentAppMerchantService; + + /** + * 检查loginId的商户是否存在 + * + * @param loginId 商户用户标识 + */ + @GetMapping("/exist") + public Boolean validPaymentAppMerchant(@RequestParam("loginId") String loginId) { + return paymentAppMerchantService.existMerchant(loginId); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 82aa7edc2..7180250b5 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -73,7 +73,7 @@ spring: app: run-tasks: false host: - main: http://dalong-au.dev.rpaygroup.com/ + main: https://1c6d-222-95-180-118.ngrok.io/ regions: au: http://dalong-au.dev.rpaygroup.com/ cn: http://dalong-au.dev.rpaygroup.com/ diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8e4176c97..16e76e99c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -174,5 +174,11 @@ logging: royalpay: payment: debug +shopify: + auth: + apiKey: 3bef8dabafd9db8c50f46ce73429f2ff + apiSecretKey: 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 + scope: write_orders,read_customers,write_payment_gateways,write_payment_sessions + diff --git a/src/main/resources/templates/shopify/auth_back.html b/src/main/resources/templates/shopify/auth_back.html new file mode 100644 index 000000000..cd6f8a9a7 --- /dev/null +++ b/src/main/resources/templates/shopify/auth_back.html @@ -0,0 +1,10 @@ + + + + + Title + + +
授权成功!
+ + \ No newline at end of file diff --git a/src/main/ui/auth.html b/src/main/ui/auth.html new file mode 100644 index 000000000..fb5650670 --- /dev/null +++ b/src/main/ui/auth.html @@ -0,0 +1,131 @@ + + + + + + RoyalPay + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + + diff --git a/src/main/ui/static/boot/shopify-auth-boot.js b/src/main/ui/static/boot/shopify-auth-boot.js new file mode 100644 index 000000000..cf66a288a --- /dev/null +++ b/src/main/ui/static/boot/shopify-auth-boot.js @@ -0,0 +1,80 @@ +/** + * Created by yixian on 2016-06-29. + */ +require.config({ + baseUrl: './', + waitSeconds: 90, + urlArgs: 'bust=' + new Date().getTime(), + paths: { + jquery: 'static/lib/jquery/jquery-2.1.4.min', + uiBootstrap: 'static/lib/angular-plugins/ui-bootstrap-tpls-1.2.4.min', + uiRouter: 'static/lib/angular-plugins/angular-ui-router.min', + angularChecklist: 'static/lib/angular-plugins/checklist-model', + angular: 'static/lib/angularjs/angular.min', + angularAnimate: 'static/lib/angularjs/angular-animate.min', + angularMessages: 'static/lib/angularjs/angular-messages.min', + angularSanitize: 'static/lib/angularjs/angular-sanitize.min', + angularLocale: 'static/lib/angularjs/angular-locale_zh-cn', + bootSwitch: 'static/lib/bootswitch/bootstrap-switch.min', + ngBootSwitch: 'static/lib/angular-plugins/angular-bootstrap-switch.min', + ngFileUpload: 'static/lib/ngfileupload/ng-file-upload.min', + holder: 'static/lib/holder/holder.min', + datetimePicker: 'static/lib/datetime-picker/datetime-picker.min', + colorpicker: 'static/lib/colorpicker/js/bootstrap-colorpicker-module.min', + qrcode: 'static/lib/jquery/jquery.qrcode.min', + sockjs: 'static/lib/websocket/sockjs.min', + stomp: 'static/lib/websocket/stomp.min', + uiSelect: 'static/lib/angular-plugins/select.min', + dragdrop: 'static/lib/angular-plugins/angular-drag-and-drop-lists.min', + echarts: 'static/lib/echarts/echarts.common.min', + angularEcharts: 'static/commons/angular-echarts', + decimal:'static/lib/decimal/decimal.min', + jstz: 'static/lib/timezone/jstz-1.0.4.min' + }, + shim: { + 'angular': {deps: ['jquery','decimal'], exports: 'angular'}, + 'angularLocale': ['angular'], + 'uiBootstrap': ['angular'], + 'uiRouter': ['angular'], + 'uiSelect': ['angular', 'css!static/lib/angular-plugins/select.min'], + 'angularAnimate': ['angular'], + 'angularMessages': ['angular'], + 'angularSanitize': ['angular'], + 'ngFileUpload': ['angular'], + 'angularChecklist': ['angular'], + 'datetimePicker': ['angular'], + 'ngBootSwitch': ['bootSwitch', 'angular'], + 'bootSwitch': ['jquery', 'css!static/lib/bootswitch/bootstrap-switch.min'], + 'qrcode': ['jquery'], + 'colorpicker': ['angular', 'css!static/lib/colorpicker/css/colorpicker.min'], + 'holder': ['jquery'], + 'dragdrop': ['angular'] + }, + map: { + '*': { + 'css': 'static/lib/css.min' + } + } +}); +var modules = [ + {path: 'static/boot/shopifyMainApp', module: 'shopifyMainApp'}, + {path: 'static/shopify/auth/shopify.auth', module: 'shopify.auth'}, + {path: 'static/shopify/auth/shopify.auth.back', module: 'shopify.auth.back'} +]; + +require(['angular', 'jquery'], function (angular, $) { + function boot() { + var paths = []; + var moduleNames = []; + angular.forEach(modules, function (mod) { + paths.push(mod.path); + moduleNames.push(mod.module); + }); + require(paths, function () { + angular.bootstrap(document.body, moduleNames) + }); + } + + boot(); + +}); diff --git a/src/main/ui/static/boot/shopifyMainApp.js b/src/main/ui/static/boot/shopifyMainApp.js new file mode 100644 index 000000000..21bd8244c --- /dev/null +++ b/src/main/ui/static/boot/shopifyMainApp.js @@ -0,0 +1,27 @@ + +define(['angular', 'angularSanitize', 'angularAnimate', 'angularMessages', 'uiRouter', 'uiBootstrap', 'ngFileUpload', 'sockjs', 'stomp'], function (angular) { + 'use strict'; + var app = angular.module('shopifyMainApp', ['ngSanitize', 'ngAnimate', 'ngMessages', 'ui.router', 'ui.bootstrap', 'ngFileUpload']); + app.config(['$urlRouterProvider', '$httpProvider','$locationProvider', function ($urlRouterProvider, $httpProvider, $locationProvider) { + $urlRouterProvider.otherwise('/shopify'); + /*$locationProvider.html5Mode({ + //设置为html5Mode(模式),当为false时为Hashbang模式 + enabled : true, + //是否需要加入base标签,这里设置为false,设置为true时,需在html的head配置标签 + requireBase : false + });*/ + if (!$httpProvider.defaults.headers.get) { + $httpProvider.defaults.headers.get = {}; + } + $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; + $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; + $httpProvider.defaults.headers.get['Pragma'] = 'no-cache'; + }]); + app.controller('ShopifyAppCtrl', ['$scope', '$rootScope', '$http', '$log', '$timeout', '$interval', '$q', '$uibModal', + function ($scope, $rootScope, $http, $log, $timeout, $interval, $q, $uibModal) { + + + + }]); + return app; +}); diff --git a/src/main/ui/static/shopify/auth/shopify.auth.back.js b/src/main/ui/static/shopify/auth/shopify.auth.back.js new file mode 100644 index 000000000..ad59b2a51 --- /dev/null +++ b/src/main/ui/static/shopify/auth/shopify.auth.back.js @@ -0,0 +1,32 @@ +define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) { + 'use strict'; + var module = angular.module('shopify.auth.back', ['ui.router', 'ui.bootstrap']); + module.config(['$stateProvider', function ($stateProvider) { + $stateProvider.state('shopifyAuthBack', { + url: '/auth_back', + templateUrl: '/static/shopify/auth/templates/shopify_auth_back.html', + controller: 'ShopifyAuthBackController' + }); + }]); + module.controller('ShopifyAuthBackController',['$scope','$http','$location', function ($scope, $http, $location) { + var that = $scope; + that.getShopifyStorePermission = function () { + var params = { + code:$location.search().code, + hmac: $location.search().hmac, + host: $location.search().host, + shop: $location.search().shop, + state: $location.search().state, + timestamp: $location.search().timestamp + } + console.log("request data:",params) + $http.post("/shopify/auth/back",params).then(function (res) { + console.log("permission data:",res.data) + }) + } + that.getShopifyStorePermission() + + }]); + return module; + } +) \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/shopify.auth.js b/src/main/ui/static/shopify/auth/shopify.auth.js new file mode 100644 index 000000000..2add776c0 --- /dev/null +++ b/src/main/ui/static/shopify/auth/shopify.auth.js @@ -0,0 +1,67 @@ +define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) { + 'use strict'; + var module = angular.module('shopify.auth', ['ui.router', 'ui.bootstrap']); + module.config(['$stateProvider', function ($stateProvider) { + $stateProvider.state('shopify', { + url: '/shopify', + templateUrl: '/static/shopify/auth/templates/auth_root.html', + controller: 'ShopifyRootController' + }).state('shopify.auth', { + url: '/auth', + templateUrl: '/static/shopify/auth/templates/shopify_auth.html', + controller: 'ShopifyAuthController' + }).state('shopify.login', { + url: '/login', + templateUrl: '/static/shopify/auth/templates/shopify_login.html', + controller: 'ShopifyLoginController' + }).state('shopify.register', { + url: '/register', + templateUrl: '/static/shopify/auth/templates/shopify_register.html', + controller: 'ShopifyRegisterController' + }); + }]); + + module.controller('ShopifyRootController',['$scope','$http','$state',function ($scope, $http, $state) { + if ($state.is('shopify')) { + $state.go('shopify.auth') + } + }]) + + module.controller('ShopifyAuthController',['$scope','$http','$state', function ($scope, $http, $state) { + var that = $scope; + that.store = { + loginId: '' + } + that.validStoreLoginId = function () { + $http.get("/shopify/store/exist",{params: that.store}).then(function (res) { + if (res.data) { + $state.go('shopify.login', {userId: that.store.loginId}); + }else { + $state.go('shopify.register', {userId: that.store.loginId}); + } + }) + } + }]); + + module.controller('ShopifyLoginController',['$scope','$http','$state', function ($scope, $http, $state) { + var that = $scope; + that.model = { + shop: '', + loginId: '', + password: '' + } + that.activeShopifyMerchant = function () { + $http.post("/shopify/auth/permission",that.model).then(function (res) { + console.log("permissionUrl",res.data.url) + location.href = res.data.url + }) + } + }]); + + module.controller('ShopifyRegisterController',['$scope','$http','$state', function ($scope, $http, $state) { + + }]); + + return module; + } +) \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/templates/auth_root.html b/src/main/ui/static/shopify/auth/templates/auth_root.html new file mode 100644 index 000000000..ccb6db5c9 --- /dev/null +++ b/src/main/ui/static/shopify/auth/templates/auth_root.html @@ -0,0 +1,40 @@ + + + + + Title + + + + +
+
+
+ +
+
+
+ +
+ +
+
+ ©2015-2021 RoyalPay. +
+
+ + \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/templates/shopify_auth.html b/src/main/ui/static/shopify/auth/templates/shopify_auth.html new file mode 100644 index 000000000..e7fa3a881 --- /dev/null +++ b/src/main/ui/static/shopify/auth/templates/shopify_auth.html @@ -0,0 +1,42 @@ + + + + + Title + + + + +
+
+
+
+

+ Connect a RoyalPay account to start accepting payments on Shopify +

+ +

+ It's free to connect, whether you have an existing RoyalPay account or want to create a new one. +

+
+
+
+ +
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/templates/shopify_auth_back.html b/src/main/ui/static/shopify/auth/templates/shopify_auth_back.html new file mode 100644 index 000000000..959a46302 --- /dev/null +++ b/src/main/ui/static/shopify/auth/templates/shopify_auth_back.html @@ -0,0 +1,14 @@ + + + + + Title + + + +
+

auth back

+
+ + + \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/templates/shopify_login.html b/src/main/ui/static/shopify/auth/templates/shopify_login.html new file mode 100644 index 000000000..6a4022f00 --- /dev/null +++ b/src/main/ui/static/shopify/auth/templates/shopify_login.html @@ -0,0 +1,54 @@ + + + + + Title + + + + +
+
+
+
+

+ Login +

+ +
+ +
+
+ +
+ +
+ + +
+ +
+ +

Example: geek-test-shop.myshopify.com

+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/ui/static/shopify/auth/templates/shopify_register.html b/src/main/ui/static/shopify/auth/templates/shopify_register.html new file mode 100644 index 000000000..29541b3ca --- /dev/null +++ b/src/main/ui/static/shopify/auth/templates/shopify_register.html @@ -0,0 +1,31 @@ + + + + + Title + + + + +
+
+
+
+

+ Register +

+
+
+
+
+ + \ No newline at end of file diff --git a/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreServiceTest.java b/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreServiceTest.java new file mode 100644 index 000000000..f71bbc825 --- /dev/null +++ b/src/test/java/au/com/royalpay/payment/manage/shopify/store/domain/service/ShopifyStoreServiceTest.java @@ -0,0 +1,44 @@ +package au.com.royalpay.payment.manage.shopify.store.domain.service; + +import au.com.royalpay.payment.manage.shopify.store.domain.entity.ShopifyStore; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Date; +import java.util.UUID; + +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({"dev", "alipay", "bestpay", "jd", "wechat", "rpay", "yeepay", "rppaysvc", "common", "alipayplusaps"}) +class ShopifyStoreServiceTest { + + @Autowired + private ShopifyStoreService shopifyStoreService; + + @Test + public void createShopifyStore() { + ShopifyStore shopifyStore = ShopifyStore.builder() + .id(UUID.randomUUID().toString()) + .clientId(00000001) + .clientMoniker("tttttt") + .shopifyShop("geek-test-shop.myshopify.com") + .createTime(new Date()) + .creator("shopify") + .modifyTime(new Date()).build(); + shopifyStoreService.createShopifyStore(shopifyStore); + } + + @Test + public void getByShopifyShop() { + ShopifyStore shopifyStore = shopifyStoreService.getByShopifyShop("geek-test-shop.myshopify.com"); + log.info(JSON.toJSONString(shopifyStore)); + } + +} \ No newline at end of file