mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Reduce steps to 1 when integrating Shopify and start adding more API calls for Shopify to reduce JS logic
This commit is contained in:
@@ -1,28 +1,32 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.StoreViewModels;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Shopify;
|
||||
using BTCPayServer.Services.Shopify.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nethereum.Util;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
{
|
||||
public partial class StoresController
|
||||
{
|
||||
|
||||
private static string _cachedBasejavascript;
|
||||
private static string _cachedShopifyJavascript;
|
||||
|
||||
private async Task<string> GetJavascript()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_cachedBasejavascript))
|
||||
if (!string.IsNullOrEmpty(_cachedShopifyJavascript))
|
||||
{
|
||||
return _cachedBasejavascript;
|
||||
return _cachedShopifyJavascript;
|
||||
}
|
||||
|
||||
string[] fileList = _BtcpayServerOptions.BundleJsCss
|
||||
@@ -35,10 +39,10 @@ namespace BTCPayServer.Controllers
|
||||
await using var stream = _webHostEnvironment.WebRootFileProvider
|
||||
.GetFileInfo(file).CreateReadStream();
|
||||
using var reader = new StreamReader(stream);
|
||||
_cachedBasejavascript += Environment.NewLine + await reader.ReadToEndAsync();
|
||||
_cachedShopifyJavascript += Environment.NewLine + await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
return _cachedBasejavascript;
|
||||
return _cachedShopifyJavascript;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
@@ -70,7 +74,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
//https://{apikey}:{password}@{hostname}/admin/api/{version}/{resource}.json
|
||||
//https://{apikey}:{password}@{hostname}/admin/api/{version}/{resource}.json
|
||||
var parsedUrl = new Uri(exampleUrl);
|
||||
var userInfo = parsedUrl.UserInfo.Split(":");
|
||||
vm.Shopify = new ShopifySettings()
|
||||
@@ -108,12 +112,20 @@ namespace BTCPayServer.Controllers
|
||||
catch
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] =
|
||||
"Shopify rejected provided credentials, please correct values and again";
|
||||
"Shopify rejected provided credentials, please correct values and try again";
|
||||
return View("Integrations", vm);
|
||||
}
|
||||
|
||||
shopify.CredentialsValid = true;
|
||||
|
||||
var scopesGranted = await apiClient.CheckScopes();
|
||||
if (!scopesGranted.Contains("read_orders") || !scopesGranted.Contains("write_script_tags"))
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] =
|
||||
"Please grant the private app permissions for read_orders, write_script_tags";
|
||||
return View("Integrations", vm);
|
||||
}
|
||||
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
blob.Shopify = shopify;
|
||||
if (CurrentStore.SetStoreBlob(blob))
|
||||
@@ -121,26 +133,7 @@ namespace BTCPayServer.Controllers
|
||||
await _Repo.UpdateStore(CurrentStore);
|
||||
}
|
||||
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Shopify credentials successfully updated";
|
||||
break;
|
||||
}
|
||||
case "ShopifyIntegrate":
|
||||
{
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
|
||||
var apiClient = new ShopifyApiClient(clientFactory, blob.Shopify.CreateShopifyApiCredentials());
|
||||
var result = await apiClient.CreateScript(Url.Action("ShopifyJavascript", "Stores",
|
||||
new {storeId = CurrentStore.Id}, Request.Scheme));
|
||||
|
||||
blob.Shopify.ScriptId = result.ScriptTag?.Id.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
blob.Shopify.IntegratedAt = DateTimeOffset.UtcNow;
|
||||
if (CurrentStore.SetStoreBlob(blob))
|
||||
{
|
||||
await _Repo.UpdateStore(CurrentStore);
|
||||
}
|
||||
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Shopify integration successfully turned on";
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Shopify integration successfully updated";
|
||||
break;
|
||||
}
|
||||
case "ShopifyClearCredentials":
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace BTCPayServer.Controllers
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
RateFetcher rateFactory,
|
||||
ExplorerClientProvider explorerProvider,
|
||||
IFeeProviderFactory feeRateProvider,
|
||||
LanguageService langService,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
SettingsRepository settingsRepository,
|
||||
@@ -82,7 +81,6 @@ namespace BTCPayServer.Controllers
|
||||
_EventAggregator = eventAggregator;
|
||||
_NetworkProvider = networkProvider;
|
||||
_ExplorerProvider = explorerProvider;
|
||||
_FeeRateProvider = feeRateProvider;
|
||||
_ServiceProvider = serviceProvider;
|
||||
_BtcpayServerOptions = btcpayServerOptions;
|
||||
_BTCPayEnv = btcpayEnv;
|
||||
@@ -93,7 +91,6 @@ namespace BTCPayServer.Controllers
|
||||
readonly IServiceProvider _ServiceProvider;
|
||||
readonly BTCPayNetworkProvider _NetworkProvider;
|
||||
private readonly ExplorerClientProvider _ExplorerProvider;
|
||||
private readonly IFeeProviderFactory _FeeRateProvider;
|
||||
readonly BTCPayWalletProvider _WalletProvider;
|
||||
readonly AccessTokenController _TokenController;
|
||||
readonly StoreRepository _Repo;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services.Shopify.ApiModels.DataHolders;
|
||||
|
||||
namespace BTCPayServer.Services.Shopify.ApiModels
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services.Shopify.ApiModels;
|
||||
using DBriize.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Shopify
|
||||
{
|
||||
@@ -23,6 +26,7 @@ namespace BTCPayServer.Services.Shopify
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
_credentials = credentials;
|
||||
|
||||
var bearer = $"{credentials.ApiKey}:{credentials.ApiPassword}";
|
||||
@@ -31,9 +35,11 @@ namespace BTCPayServer.Services.Shopify
|
||||
_httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + bearer);
|
||||
}
|
||||
|
||||
private HttpRequestMessage CreateRequest(string shopName, HttpMethod method, string action)
|
||||
private HttpRequestMessage CreateRequest(string shopName, HttpMethod method, string action,
|
||||
string relativeUrl = null)
|
||||
{
|
||||
var url = $"https://{(shopName.Contains(".", StringComparison.InvariantCulture)? shopName: $"{shopName}.myshopify.com")}/admin/api/2020-07/" + action;
|
||||
var url =
|
||||
$"https://{(shopName.Contains(".", StringComparison.InvariantCulture) ? shopName : $"{shopName}.myshopify.com")}/{relativeUrl ?? ("admin/api/2020-07/" + action)}";
|
||||
var req = new HttpRequestMessage(method, url);
|
||||
return req;
|
||||
}
|
||||
@@ -49,12 +55,8 @@ namespace BTCPayServer.Services.Shopify
|
||||
public async Task<CreateWebhookResponse> CreateWebhook(string topic, string address, string format = "json")
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Post, $"webhooks.json");
|
||||
req.Content = new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
topic,
|
||||
address,
|
||||
format
|
||||
}), Encoding.UTF8, "application/json");
|
||||
req.Content = new StringContent(JsonConvert.SerializeObject(new {topic, address, format}), Encoding.UTF8,
|
||||
"application/json");
|
||||
var strResp = await SendRequest(req);
|
||||
|
||||
return JsonConvert.DeserializeObject<CreateWebhookResponse>(strResp);
|
||||
@@ -63,18 +65,24 @@ namespace BTCPayServer.Services.Shopify
|
||||
public async Task RemoveWebhook(string id)
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Delete, $"webhooks/{id}.json");
|
||||
await SendRequest(req);
|
||||
var strResp = await SendRequest(req);
|
||||
}
|
||||
|
||||
public async Task<CreateScriptResponse> CreateScript(string scriptUrl, string evt = "onload", string scope = "order_status")
|
||||
public async Task<string[]> CheckScopes()
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Delete, null, "admin/oauth/access_scopes.json");
|
||||
return JObject.Parse(await SendRequest(req))["access_scopes"].Values<JToken>()
|
||||
.Select(token => token["handle"].Value<string>()).ToArray();
|
||||
}
|
||||
|
||||
public async Task<CreateScriptResponse> CreateScript(string scriptUrl, string evt = "onload",
|
||||
string scope = "order_status")
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Post, $"script_tags.json");
|
||||
req.Content = new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
@event = evt,
|
||||
src = scriptUrl,
|
||||
display_scope = scope
|
||||
}), Encoding.UTF8, "application/json");
|
||||
req.Content =
|
||||
new StringContent(
|
||||
JsonConvert.SerializeObject(new {@event = evt, src = scriptUrl, display_scope = scope}),
|
||||
Encoding.UTF8, "application/json");
|
||||
var strResp = await SendRequest(req);
|
||||
|
||||
return JsonConvert.DeserializeObject<CreateScriptResponse>(strResp);
|
||||
@@ -108,6 +116,26 @@ namespace BTCPayServer.Services.Shopify
|
||||
return JsonConvert.DeserializeObject<TransactionsCreateResp>(strResp);
|
||||
}
|
||||
|
||||
public async Task UpdateOrderNote(string orderId, string note)
|
||||
{
|
||||
var postJson = JsonConvert.SerializeObject(new {order = new {id = orderId, note}});
|
||||
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Put, $"orders/{orderId}.json");
|
||||
req.Content = new StringContent(postJson, Encoding.UTF8, "application/json");
|
||||
|
||||
await SendRequest(req);
|
||||
}
|
||||
|
||||
public async Task<ShopifyOrder> GetOrder(string orderId)
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Get,
|
||||
$"orders/{orderId}.json?fields=id,total_price,currency,transactions,financial_status");
|
||||
|
||||
var strResp = await SendRequest(req);
|
||||
|
||||
return JsonConvert.DeserializeObject<ShopifyOrder>(strResp);
|
||||
}
|
||||
|
||||
public async Task<long> OrdersCount()
|
||||
{
|
||||
var req = CreateRequest(_credentials.ShopName, HttpMethod.Get, $"orders/count.json");
|
||||
@@ -126,11 +154,11 @@ namespace BTCPayServer.Services.Shopify
|
||||
return strResp?.Contains(orderId, StringComparison.OrdinalIgnoreCase) == true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ShopifyApiClientCredentials
|
||||
{
|
||||
public class ShopifyApiClientCredentials
|
||||
{
|
||||
public string ShopName { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
public string ApiPassword { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ function promptExampleUrl(){
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Checkout scripts should be automatically added to the order status page to display the BTCPay payment option.</p>
|
||||
<p class="alert alert-success">Checkout scripts should be automatically added to the order status page to display the BTCPay payment option.</p>
|
||||
}
|
||||
<p class="alert alert-info">
|
||||
Please add a payment method at <a href="https://@(shopify.ShopName).myshopify.com/admin/settings/payments" target="_blank"> Settings > Payments > Manual Payment Methods</a> with the name <kbd>Bitcoin with BTCPay Server</kbd>
|
||||
@@ -90,10 +90,6 @@ function promptExampleUrl(){
|
||||
|
||||
@if (shopifyCredsSet)
|
||||
{
|
||||
if (!shopify.IntegratedAt.HasValue)
|
||||
{
|
||||
<button name="command" type="submit" class="btn btn-primary" value="ShopifyIntegrate">Integrate Shopify Order Paid Marking</button>
|
||||
}
|
||||
<button name="command" type="submit" class="btn btn-danger" value="ShopifyClearCredentials">
|
||||
@(shopify.IntegratedAt.HasValue ? "Stop Shopify calls and clear credentials" : "Clear credentials")
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user