upgrade shopify OAuth process

master
ycfxx 4 years ago
parent 5da0ab76b3
commit 4bcdf212c5

@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCu
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.io.File;
@ -31,6 +32,7 @@ import java.util.concurrent.TimeUnit;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableScheduling
@EnableCaching(proxyTargetClass = true)
@EnableAsync
public class PaymentManageApplication {
public static void main(String[] args) {

@ -26,7 +26,7 @@ import java.util.Date;
@Component
public class ShopifyMerchantAuthApplication {
@Value("${shopify.version:2021-10}")
@Value("${shopify.version:2022-01}")
private String apiVersion;
@Value("${shopify.auth.apiKey}")
@ -53,34 +53,61 @@ public class ShopifyMerchantAuthApplication {
private PaymentsAppConfigureClient paymentsAppConfigureClient;
/**
* shopifyURL
* shopifyurl
* @param shopifyStoreHost
* @param hmac
* @param timestamp
* @return
*/
public ShopifyPermissionURL getShopifyPermissionUrl(String shopifyStoreHost, String hmac, String timestamp) {
ShopifyPermissionURL shopifyPermissionURL = shopifyAuthService.shopifyPermission(shopifyStoreHost, hmac, timestamp);
return shopifyPermissionURL;
}
/**
* shopify
*
* @param request
* @return
*/
public ShopifyPermissionURL shopifyPermission(ShopifyPermissionRequest request) {
public ShopifyAccessToken install(ShopifyPermissionRequest request) {
LoginInfo loginInfo = new LoginInfo();
loginInfo.setLoginId(request.getLoginId());
loginInfo.setPassword(request.getPassword());
signInStatusManager.partnerSignIn(loginInfo);
SimpleMerchantAccount simpleMerchantAccount = merchantAccountService.getByUsername(request.getLoginId());
String shop = request.getShop();
SimpleMerchantAccount simpleMerchantAccount = merchantAccountService.getByUsername(request.getLoginId());
SimpleMerchant simpleMerchant = merchantService.getByClientId(simpleMerchantAccount.getClientId());
ShopifyStore shopifyShop = shopifyStoreService.getByShopifyShop(request.getShop());
ShopifyStore shopifyShop = shopifyStoreService.getByShopifyShop(shop);
ShopifyAccessToken accessToken = shopifyAuthService.getAccessToken(shop, request.getCode());
if (shopifyShop == null) {
shopifyStoreService.createShopifyStore(ShopifyStore.instanceOf(simpleMerchantAccount, simpleMerchant, request.getShop()));
return shopifyAuthService.shopifyPermission(request);
shopifyStoreService.createShopifyStore(ShopifyStore.instanceOf(simpleMerchantAccount, simpleMerchant, shop, accessToken));
return getShopifyPaymentAppConfigUrl(shop, accessToken);
}
shopifyStoreService.modifyShopifyStore(shopifyShop
.setClientId(simpleMerchantAccount.getClientId())
.setClientMoniker(simpleMerchant.getClientMoniker())
.setModifyTime(new Date())
.setModifier(request.getShop()));
.setAccessToken(accessToken.getAccess_token())
.setScope(accessToken.getScope())
.setModifier(shop));
return getShopifyPaymentAppConfigUrl(shop, accessToken);
}
private ShopifyAccessToken getShopifyPaymentAppConfigUrl(String shop, ShopifyAccessToken accessToken) {
try {
paymentsAppConfigureClient.paymentsAppConfigure(shop, true, apiVersion);
} catch (IOException e) {
log.error(String.format("Shopify store [%s] payment app setting error: %s", shop, e.getMessage()));
throw new BadRequestException("Payment app setting error");
}
return shopifyAuthService.shopifyPermission(request);
String redirectUrl = String.format(PAYMENT_SETTING_URL, shop, apiKey);
return accessToken.setRedirectUrl(redirectUrl);
}
/**
@ -90,6 +117,7 @@ public class ShopifyMerchantAuthApplication {
* @param code code
* @return
*/
@Deprecated
public ShopifyAccessToken merchantOnboard(String shop, String code) {
ShopifyAccessToken accessToken = shopifyAuthService.getAccessToken(shop, code);
ShopifyStore shopifyStore = shopifyStoreService.getByShopifyShop(shop);
@ -98,14 +126,8 @@ public class ShopifyMerchantAuthApplication {
}
shopifyStoreService.modifyShopifyStore(shopifyStore.setAccessToken(accessToken.getAccess_token()).setScope(accessToken.getScope()));
try {
paymentsAppConfigureClient.paymentsAppConfigure(shop, true, apiVersion);
} catch (IOException e) {
log.error(String.format("Shopify store [%s] payment app setting error: %s", shop, e.getMessage()));
throw new BadRequestException("Payment app setting error");
return getShopifyPaymentAppConfigUrl(shop, accessToken);
}
String redirectUrl = String.format(PAYMENT_SETTING_URL, shop, apiKey);
return accessToken.setRedirectUrl(redirectUrl);
}
}

@ -38,9 +38,9 @@ public class ShopifyAuthService {
@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));
public ShopifyPermissionURL shopifyPermission(String shopifyStoreHost, String hmac, String timestamp) {
String redirectUri = PlatformEnvironment.getEnv().concatUrl("/auth.html#/shopify/login");
String permissionUrl = String.format(PERMISSION_URL, shopifyStoreHost, clientId, scope, redirectUri, String.valueOf(new Date().getTime()).substring(0,10));
return ShopifyPermissionURL.builder().url(permissionUrl).build();
}
@ -57,4 +57,5 @@ public class ShopifyAuthService {
log.info(String.format("Shopify merchant [%s] access token: %s", shop, shopifyAccessToken));
return shopifyAccessToken;
}
}

@ -2,11 +2,12 @@ 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 org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@ -26,28 +27,9 @@ public class ShopifyAuthController {
* @param request
* @return
*/
@PostMapping("/permission")
public ShopifyPermissionURL shopifyPermission(@RequestBody @Valid ShopifyPermissionRequest request) {
ShopifyPermissionURL shopifyPermissionURL = shopifyMerchantAuthApplication.shopifyPermission(request);
return shopifyPermissionURL;
@PostMapping("/install")
public ShopifyAccessToken shopifyPermission(@RequestBody @Valid ShopifyPermissionRequest request) {
ShopifyAccessToken shopifyAccessToken = shopifyMerchantAuthApplication.install(request);
return shopifyAccessToken;
}
/**
* 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;
}
}

@ -0,0 +1,35 @@
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.ShopifyPermissionURL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.servlet.view.RedirectView;
@Controller
@RequestMapping(value = "/shopify")
public class ShopifyAuthTemplateController {
@Autowired
private ShopifyMerchantAuthApplication shopifyMerchantAuthApplication;
/**
* shopify
*
* @param shopifyStoreHost
* @param hmac
* @param timestamp
* @return
*/
@GetMapping("/auth")
public RedirectView shopifyStoreInstall(@RequestParam("shop") String shopifyStoreHost,
@RequestParam("hmac") String hmac,
@RequestParam("timestamp") String timestamp) {
ShopifyPermissionURL shopifyPermissionURL = shopifyMerchantAuthApplication.getShopifyPermissionUrl(shopifyStoreHost, hmac, timestamp);
return new RedirectView(shopifyPermissionURL.getUrl());
}
}

@ -23,11 +23,15 @@ public class ShopifyPermissionRequest {
@NotBlank(message = "Password can not blank")
private String password;
@NotBlank(message = "Code can not blank")
private String code;
public static ShopifyPermissionRequest instanceOf(CreateShopifyMerchantCommand command) {
return ShopifyPermissionRequest.builder()
.loginId(command.getPaymentAccount().getLoginId())
.password(command.getPaymentAccount().getPassword())
.shop(command.getShopifyShop())
.code(command.getCode())
.build();
}
}

@ -0,0 +1,57 @@
package au.com.royalpay.payment.manage.shopify.hooks;
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 com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping(value = "/shopify")
public class ShopifyWebhooksController {
@Autowired
private ShopifyStoreService shopifyStoreService;
/**
*
*
* @param command
*/
@PostMapping("/customer/request")
public void customerRequest(ShopifyCustomerRequestCommand command) {
log.warn(JSON.toJSONString(command));
}
/**
*
*
* @param command
*/
@PostMapping("/customer/erasure")
public void customerRedact(ShopifyCustomerRedactCommand command) {
log.warn(JSON.toJSONString(command));
}
/**
* shopifypayment app
*
* @param command
*/
@PostMapping("/shop/erasure")
public void shopRedact(ShopifyShopRedactCommand command) {
log.warn(JSON.toJSONString(command));
ShopifyStore shopifyShop = shopifyStoreService.getByShopifyShop(command.getShop_domain());
if (shopifyShop == null) {
return;
}
shopifyStoreService.modifyShopifyStore(shopifyShop.setStatus(0));
}
}

@ -0,0 +1,10 @@
package au.com.royalpay.payment.manage.shopify.hooks.command;
import lombok.Data;
@Data
public class ShopifyCustomer {
private String id;
private String email;
private String phone;
}

@ -0,0 +1,13 @@
package au.com.royalpay.payment.manage.shopify.hooks.command;
import lombok.Data;
import java.util.List;
@Data
public class ShopifyCustomerRedactCommand {
private String shop_id;
private String shop_domain;
private ShopifyCustomer customer;
private List<Long> orders_to_redact;
}

@ -0,0 +1,19 @@
package au.com.royalpay.payment.manage.shopify.hooks.command;
import lombok.Data;
import java.util.List;
@Data
public class ShopifyCustomerRequestCommand {
private String shop_id;
private String shop_domain;
private List<Long> orders_requested;
private ShopifyCustomer customer;
private DataRequest data_request;
@Data
public class DataRequest{
private String id;
}
}

@ -0,0 +1,9 @@
package au.com.royalpay.payment.manage.shopify.hooks.command;
import lombok.Data;
@Data
public class ShopifyShopRedactCommand {
private String shop_id;
private String shop_domain;
}

@ -1,7 +1,7 @@
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.ShopifyPermissionURL;
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;
@ -56,7 +56,7 @@ public class ShopifyStoreApplication implements ApplicationEventPublisherAware {
* @return
*/
@Transactional
public ShopifyPermissionURL register(CreateShopifyMerchantCommand command) {
public ShopifyAccessToken register(CreateShopifyMerchantCommand command) {
MerchantCreateContext merchantCreateContext = new MerchantCreateContext(platformMerchantProvider, command);
SimpleMerchant simpleMerchant = merchantservice.createMerchant(merchantCreateContext);
@ -64,11 +64,11 @@ public class ShopifyStoreApplication implements ApplicationEventPublisherAware {
MerchantAccountRequest accountRequest = MerchantAccountRequest.instanceOf(command, simpleMerchant);
merchantAccountService.createAccount(accountRequest);
ShopifyPermissionURL shopifyPermissionURL = shopifyMerchantAuthApplication.shopifyPermission(ShopifyPermissionRequest.instanceOf(command));
ShopifyAccessToken shopifyAccessToken = shopifyMerchantAuthApplication.install(ShopifyPermissionRequest.instanceOf(command));
this.eventPublisher.publishEvent(new ShopifyStoreCreatedEvent(this,simpleMerchant,command,accountRequest));
this.eventPublisher.publishEvent(new ShopifyStoreCreatedEvent(this, simpleMerchant, command, accountRequest));
return shopifyPermissionURL;
return shopifyAccessToken;
}

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.shopify.store.domain.entity;
import au.com.royalpay.payment.manage.shopify.auth.domain.entity.ShopifyAccessToken;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -36,7 +37,9 @@ public class ShopifyStore {
private String scope;
public static ShopifyStore instanceOf(SimpleMerchantAccount merchantAccount, SimpleMerchant simpleMerchant, String shop) {
private int status;
public static ShopifyStore instanceOf(SimpleMerchantAccount merchantAccount, SimpleMerchant simpleMerchant, String shop, ShopifyAccessToken accessToken) {
return ShopifyStore.builder()
.id(UUID.randomUUID().toString())
.clientId(merchantAccount.getClientId())
@ -44,6 +47,8 @@ public class ShopifyStore {
.shopifyShop(shop)
.createTime(new Date())
.creator("shopify store")
.accessToken(accessToken.getAccess_token())
.scope(accessToken.getScope())
.modifyTime(new Date()).build();
}
}

@ -1,5 +1,6 @@
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.auth.domain.entity.ShopifyPermissionURL;
import au.com.royalpay.payment.manage.shopify.store.domain.application.ShopifyStoreApplication;
import au.com.royalpay.payment.manage.shopify.store.web.command.CreateShopifyMerchantCommand;
@ -35,7 +36,7 @@ public class ShopifyStoreController {
* @Return
*/
@PostMapping("/register")
public ShopifyPermissionURL createMerchantWithShopify(@RequestBody @Valid CreateShopifyMerchantCommand command) {
public ShopifyAccessToken createMerchantWithShopify(@RequestBody @Valid CreateShopifyMerchantCommand command) {
return shopifyStoreApplication.register(command);
}
}

@ -15,4 +15,7 @@ public class CreateShopifyMerchantCommand {
@NotBlank(message = "Shop can not blank")
private String shopifyShop;
@NotBlank(message = "Auth code can not blank")
private String code;
}

@ -1,7 +1,24 @@
define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
'use strict';
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return null;
}
var module = angular.module('shopify.auth', ['ui.router', 'ui.bootstrap', 'ngMessages']);
module.config(['$stateProvider', function ($stateProvider) {
module.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
$locationProvider.html5Mode({
enabled: false,
requireBase: false
});
$stateProvider.state('shopify', {
url: '/shopify',
templateUrl: '/static/shopify/auth/templates/auth_root.html',
@ -13,19 +30,19 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
}).state('shopify.login', {
url: '/login',
templateUrl: '/static/shopify/auth/templates/shopify_login.html',
params: {'userId': null},
params: {'shop': null, 'code': null},
controller: 'ShopifyLoginController'
}).state('shopify.register', {
url: '/register',
templateUrl: '/static/shopify/auth/templates/shopify_register.html',
params: {'userId': null},
params: {'shop': null, 'code': null},
controller: 'ShopifyRegisterController'
});
}]);
module.controller('ShopifyRootController', ['$scope', '$http', '$state', function ($scope, $http, $state) {
if ($state.is('shopify')) {
$state.go('shopify.auth')
$state.go('shopify.login')
}
}])
@ -43,36 +60,37 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
} else {
$state.go('shopify.register', {partnerCode: that.store.partnerCode});
}
},function (error) {
}, function (error) {
that.resError = error.data.message;
that.authDisable = false
})
}
that.registerMerchant = function () {
$state.go('shopify.register');
}
}]);
module.controller('ShopifyLoginController', ['$scope', '$http', '$stateParams', function ($scope, $http, $stateParams) {
module.controller('ShopifyLoginController', ['$scope', '$http', '$state', '$stateParams', '$location', function ($scope, $http, $state, $stateParams, $location) {
var that = $scope;
that.model = {
shop: '',
partnerCode: $stateParams.partnerCode,
shop: getQueryVariable("shop"),
loginId: '',
password: ''
password: '',
code: getQueryVariable("code")
}
that.loginDisable = false
that.activeShopifyMerchant = function () {
that.loginDisable = true
$http.post("/shopify/auth/permission", that.model).then(function (res) {
console.log("permissionUrl", res.data.url)
location.href = res.data.url
},function (error) {
$http.post("/shopify/auth/install", that.model).then(function (res) {
console.log("redirectUrl", res.data.redirectUrl)
location.href = res.data.redirectUrl
}, function (error) {
that.resError = error.data.message;
that.loginDisable = false
})
}
that.registerMerchant = function () {
$state.go('shopify.register', {shop: getQueryVariable("shop"), code: getQueryVariable("code")});
}
}]);
module.controller('ShopifyRegisterController', ['$scope', '$http', '$stateParams', function ($scope, $http, $stateParams) {
@ -223,10 +241,11 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
const param = {
paymentMerchant,
paymentAccount,
shopifyShop: that.partner.shopifyShop
shopifyShop: $stateParams.shop,
code: $stateParams.code
}
$http.post('shopify/store/register', param).then(function (resp) {
location.href = resp.data.url
location.href = resp.data.redirectUrl
}, function (error) {
that.resError = error.data.message;
that.registerDisable = false

@ -5,7 +5,7 @@
<title>Title</title>
<style>
.col-centered{
.col-centered {
float: none;
margin: 0 auto;
}
@ -28,22 +28,26 @@
<form>
<div class="form-group form-group-lg">
<input class="form-control input-lg" id="exampleInputEmail" placeholder="Login ID" ng-model="model.loginId">
<input class="form-control input-lg" id="exampleInputEmail" placeholder="Login ID"
ng-model="model.loginId">
</div>
<div class="form-group form-group-lg">
<input type="password" class="form-control" id="exampleInputPassword" placeholder="Password" ng-model="model.password">
<input type="password" class="form-control" id="exampleInputPassword" placeholder="Password"
ng-model="model.password">
</div>
<div class="form-group form-group-lg">
<input class="form-control input-lg" id="shopifyShop" placeholder="Shop" ng-model="model.shop">
<p class="help-block">Example: geek-test-shop.myshopify.com</p>
</div>
<button class="btn btn-warning btn-lg btn-block m-t-40" ng-disabled="loginDisable" ng-click="activeShopifyMerchant()">Log In</button>
<button class="btn btn-warning btn-lg btn-block m-t-40" ng-disabled="loginDisable"
ng-click="activeShopifyMerchant()">Log In
</button>
<div>
<p ng-if="resError" style="padding: 6px 12px;font-size: 14px;"
class="small text-danger">{{resError}}</p>
</div>
<div class="m-t-10"></div>
<span style="padding-top: 15px">
Not a RoyalPay merchant yet, <a href="" ng-click="registerMerchant()">please register</a>
</span>
</form>
</div>
</div>

@ -53,7 +53,7 @@
</div>
</div>
<div class="form-group has-feedback"
<!--<div class="form-group has-feedback"
ng-class="{'has-error':partnerForm.shopifyShop.$invalid && partnerForm.shopifyShop.$dirty}">
<input type="text" class="form-control" ng-model="partner.shopifyShop" name="shopifyShop"
placeholder="Shop" required>
@ -62,7 +62,7 @@
ng-if="partnerForm.shopifyShop.$dirty">
<p class="small text-danger" ng-message="required">Required Field</p>
</div>
</div>
</div>-->
<div class="form-group has-feedback"
ng-class="{'has-error':partnerForm.companyName.$invalid && partnerForm.companyName.$dirty}">

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.shopify.store.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.store.web.command.CreateShopifyMerchantCommand;
import au.com.royalpay.payment.manage.shopify.store.web.command.PaymentAccountCommand;
@ -46,7 +47,7 @@ class ShopifyStoreApplicationTest {
.setPaymentAccount(accountCommand)
.setShopifyShop("demo.myshopify.com");
ShopifyPermissionURL shopifyPermissionURL = shopifyStoreApplication.register(command);
log.warn(JSON.toJSONString(shopifyPermissionURL));
ShopifyAccessToken shopifyAccessToken = shopifyStoreApplication.register(command);
log.warn(JSON.toJSONString(shopifyAccessToken));
}
}
Loading…
Cancel
Save