示例#1
0
        public IHttpActionResult Connect(string code, string shop, string hmac, string state)
        {
            if (!ShopifyAuthorizationService.IsValidMyShopifyUrl(shop))
            {
                return(BadRequest());
            }

            var queryString = HttpUtility.ParseQueryString(Request.RequestUri.Query);

            if (!ShopifyAuthorizationService.IsAuthenticRequest(queryString, SystemSettings.ApiSecret))
            {
                return(BadRequest());
            }

            var store = _storeService.GetByHost(shop);

            if (store.Nonce != state)
            {
                return(BadRequest());
            }

            var authService = new ShopifyAuthorizationService(new ShopifySettings()
            {
                AuthenticationType = AuthenticationType.AccessToken,
                HostName           = shop
            });

            var accessToken = authService.Authorize(code, SystemSettings.ApiKey, SystemSettings.ApiSecret);

            if (string.IsNullOrEmpty(accessToken))
            {
                return(BadRequest());
            }

            store.AccessToken = accessToken;
            store.Code        = code;
            store.Options    &= ~StoreOptions.Disabled;

            _storeService.Update(store);

            var webhookService = new ShopifyWebhookService(new ShopifySettings(shop, accessToken));

            webhookService.Create(new ShopifyWebhook()
            {
                Topic   = ShopifyWebhookTopic.AppUninstalled,
                Address = SystemSettings.UninstallUrl,
                Format  = "json"
            });

            return(Redirect(ShopifyAuthorizationService.BuildShopUri(shop)));
        }
示例#2
0
        public ShopifyRoute() : base("/api/v1/shopify")
        {
            Post["/authorize", true] = async(parameters, ct) =>
            {
                var model = this.BindAndValidate <AuthorizeRequest>();

                if (!ModelValidationResult.IsValid)
                {
                    return(Response.AsJsonError("Request did not pass validation.", HttpStatusCode.NotAcceptable, ModelValidationResult.FormattedErrors));
                }

                var getUser = await Database.Users.Entities.GetAsync <User>(SessionToken.UserId);

                if (!getUser.IsSuccess)
                {
                    return(Response.AsJsonError("Could not find user in database.", HttpStatusCode.NotFound));
                }

                // Complete the OAuth process and integrate the user
                var    user = getUser.Content;
                string accessToken;

                try
                {
                    accessToken = await ShopifyAuthorizationService.Authorize(model.Code, model.ShopUrl, Config.ShopifyApiKey, Config.ShopifySecretKey);
                }
                catch (ShopifyException e) when(e.JsonError.ContainsIgnoreCase("authorization code was not found or was already used"))
                {
                    return(Response.AsJsonError("Integration failed: the authorization code was not found or was already used.", HttpStatusCode.BadRequest));
                }

                var shop = await new ShopifyShopService(model.ShopUrl, accessToken).GetAsync();

                user.ShopifyAccessToken = accessToken;
                user.ShopifyUrl         = model.ShopUrl;
                user.ShopId             = shop.Id;
                user.ShopName           = shop.Name;
                user.Permissions        = Config.ShopifyPermissions;

                // Create an App_Uninstalled webhook if we're not running on localhost
                if (!Regex.IsMatch(Request.Url.HostName, "localhost", RegexOptions.IgnoreCase))
                {
                    var service = new ShopifyWebhookService(user.ShopifyUrl, user.ShopifyAccessToken);
                    var url     = new UriBuilder(Request.Url.ToString())
                    {
                        Scheme = Uri.UriSchemeHttps, // All Shopify webhooks must be https
                        Path   = "/api/v1/webhooks/app_uninstalled",
                        Query  = $"shop_id={shop.Id.Value}",
                    };

                    try
                    {
                        await service.CreateAsync(new ShopifyWebhook()
                        {
                            Address = url.ToString(),
                            Topic   = "app/uninstalled",
                        });
                    }
                    catch (ShopifyException ex) when(ex.Errors.Any(e => e.Key.EqualsIgnoreCase("address") && e.Value.Any(innerError => innerError.ContainsIgnoreCase("for this topic has already been taken"))))
                    {
                        // Webhook already exists.
                    }
                }

                // Update the user
                var update = await Database.Users.Entities.PutAsync(user);

                if (!update.IsSuccess)
                {
                    throw new Exception($"Failed to save user's integration. {(int)update.StatusCode} {update.Reason}");
                }

                return(Response.WithSessionToken(user));
            };

            Post["/activate_charge", true] = async(parameters, ct) =>
            {
                long chargeId = parameters.charge_id;
                var  getUser  = await Database.Users.Entities.GetAsync <User>(this.SessionToken.UserId);

                if (!getUser.IsSuccess)
                {
                    throw new Exception("User not found.");
                }

                // Activate the charge if its status is accepted.
                var user    = getUser.Content;
                var service = new ShopifyRecurringChargeService(user.ShopifyUrl, user.ShopifyAccessToken);
                var charge  = await service.GetAsync(chargeId);

                if (charge.Status != "accepted")
                {
                    throw new Exception($"Charge #${charge.Id.Value} has not been accepted.");
                }

                // Update the user
                var update = await Database.Users.Entities.PutAsync(user);

                if (!update.IsSuccess)
                {
                    throw new Exception($"Failed to save user's new charge. {update.StatusCode} {update.Reason}");
                }

                return(Response.WithSessionToken(user));
            };

            Post["/create_authorization_url"] = (parameters) =>
            {
                var model = this.Bind <CreateAuthorizationUrlRequest>();
                var url   = ShopifyAuthorizationService.BuildAuthorizationUrl(Config.ShopifyPermissions, model.Url, Config.ShopifyApiKey, model.RedirectUrl);

                return(Response.AsJson(new
                {
                    url = url
                }));
            };

            Get["/orders", true] = async(parameters, ct) =>
            {
                int?   limit   = Request.Query.limit;
                int?   page    = Request.Query.page;
                string status  = Request.Query.status ?? "any";
                var    service = new ShopifyOrderService(SessionToken.ShopifyUrl, SessionToken.ShopifyAccessToken);
                var    orders  = await service.ListAsync(new ShopifySharp.Filters.ShopifyOrderFilter()
                {
                    Limit  = limit,
                    Page   = page,
                    Status = "any",
                });

                return(Response.AsJson(orders));
            };

            Post["/orders", true] = async(parameters, ct) =>
            {
                var model = this.BindAndValidate <CreateOrderRequest>();

                if (!ModelValidationResult.IsValid)
                {
                    return(Response.AsJsonError("Request did not pass validation.", HttpStatusCode.NotAcceptable, ModelValidationResult.FormattedErrors));
                }

                var service = new ShopifyOrderService(SessionToken.ShopifyUrl, SessionToken.ShopifyAccessToken);
                var order   = await service.CreateAsync(new ShopifyOrder()
                {
                    CreatedAt      = DateTime.UtcNow,
                    BillingAddress = new ShopifyAddress()
                    {
                        Address1    = model.Street,
                        City        = model.City,
                        Province    = model.State,
                        Zip         = model.Zip,
                        Name        = model.Name,
                        CountryCode = "US",
                        Default     = true,
                    },
                    LineItems = new List <ShopifyLineItem>()
                    {
                        new ShopifyLineItem()
                        {
                            Name     = model.LineItem,
                            Title    = model.LineItem,
                            Quantity = model.Quantity,
                            Price    = 5,
                        },
                    },
                    FinancialStatus = "authorized",
                    Email           = model.Email,
                });

                return(Response.AsJson(order).WithStatusCode(HttpStatusCode.Created));
            };

            Post["/orders/{id:long}/{verb}", true] = async(parameters, ct) =>
            {
                string verb = parameters.verb;
                long   id   = parameters.id;

                if (!verb.EqualsIgnoreCase("open") && !verb.EqualsIgnoreCase("close"))
                {
                    return(Negotiate.WithStatusCode(HttpStatusCode.MethodNotAllowed));
                }

                if (!ModelValidationResult.IsValid)
                {
                    return(Response.AsJsonError("Request did not pass validation.", HttpStatusCode.NotAcceptable, ModelValidationResult.FormattedErrors));
                }

                var service = new ShopifyOrderService(SessionToken.ShopifyUrl, SessionToken.ShopifyAccessToken);

                if (verb.EqualsIgnoreCase("open"))
                {
                    await service.OpenAsync(id);
                }
                else
                {
                    await service.CloseAsync(id);
                }

                // Refresh the order and return it to the client
                var order = await service.GetAsync(id);

                return(Response.AsJson(order));
            };

            Delete["/orders/{id:long}", true] = async(parameters, ct) =>
            {
                long id      = parameters.id;
                var  service = new ShopifyOrderService(SessionToken.ShopifyUrl, SessionToken.ShopifyAccessToken);

                await service.DeleteAsync(id);

                return(Negotiate.WithStatusCode(200));
            };
        }