mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 14:22:40 +01:00
Importing UI for registering and verifying Shopify credentials
This commit is contained in:
parent
cf99f0fca0
commit
8a68e1b49d
5 changed files with 230 additions and 12 deletions
|
@ -20,6 +20,7 @@ using BTCPayServer.Services;
|
|||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Shopify;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -964,5 +965,89 @@ namespace BTCPayServer.Controllers
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
[HttpGet]
|
||||
[Route("{storeId}/integrations")]
|
||||
public async Task<IActionResult> Integrations()
|
||||
{
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
|
||||
var vm = new IntegrationsViewModel
|
||||
{
|
||||
Shopify = blob.Shopify
|
||||
};
|
||||
|
||||
return View("Integrations", vm);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("{storeId}/integrations")]
|
||||
public async Task<IActionResult> Integrations([FromServices] IHttpClientFactory clientFactory,
|
||||
IntegrationsViewModel vm, string command = "")
|
||||
{
|
||||
if (command == "ShopifySaveCredentials")
|
||||
{
|
||||
var shopify = vm.Shopify;
|
||||
var validCreds = shopify != null && shopify?.CredentialsPopulated() == true;
|
||||
if (!validCreds)
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] = "Please provide valid Shopify credentials";
|
||||
//
|
||||
return View("Integrations", vm);
|
||||
}
|
||||
|
||||
var apiCreds = new ShopifyApiClientCredentials
|
||||
{
|
||||
ShopName = shopify.ShopName,
|
||||
ApiKey = shopify.ApiKey,
|
||||
ApiPassword = shopify.Password,
|
||||
SharedSecret = shopify.SharedSecret
|
||||
};
|
||||
|
||||
var apiClient = new ShopifyApiClient(clientFactory, null, apiCreds);
|
||||
try
|
||||
{
|
||||
var result = await apiClient.OrdersCount();
|
||||
}
|
||||
catch
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] = "Shopify rejected provided credentials, please correct values and again";
|
||||
//
|
||||
return View("Integrations", vm);
|
||||
}
|
||||
|
||||
|
||||
shopify.CredentialsValid = true;
|
||||
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
blob.Shopify = shopify;
|
||||
if (CurrentStore.SetStoreBlob(blob))
|
||||
{
|
||||
await _Repo.UpdateStore(CurrentStore);
|
||||
}
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Shopify credentials successfully updated";
|
||||
}
|
||||
else if (command == "ShopifyIntegrate")
|
||||
{
|
||||
var shopify = vm.Shopify;
|
||||
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
blob.Shopify.IntegratedAt = DateTimeOffset.UtcNow;
|
||||
if (CurrentStore.SetStoreBlob(blob))
|
||||
{
|
||||
await _Repo.UpdateStore(CurrentStore);
|
||||
}
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Shopify integration successfully turned on";
|
||||
}
|
||||
|
||||
return RedirectToAction(nameof(Integrations), new
|
||||
{
|
||||
storeId = CurrentStore.Id
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,28 @@ namespace BTCPayServer.Data
|
|||
RecommendedFeeBlockTarget = 1;
|
||||
}
|
||||
|
||||
public ShopifyDataHolder Shopify { get; set; }
|
||||
|
||||
public class ShopifyDataHolder
|
||||
{
|
||||
public string ShopName { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string SharedSecret { get; set; }
|
||||
|
||||
public bool CredentialsPopulated()
|
||||
{
|
||||
return
|
||||
!String.IsNullOrWhiteSpace(ShopName) &&
|
||||
!String.IsNullOrWhiteSpace(ApiKey) &&
|
||||
!String.IsNullOrWhiteSpace(Password) &&
|
||||
!String.IsNullOrWhiteSpace(SharedSecret);
|
||||
}
|
||||
public bool CredentialsValid { get; set; }
|
||||
|
||||
public DateTimeOffset? IntegratedAt { get; set; }
|
||||
}
|
||||
|
||||
[Obsolete("Use NetworkFeeMode instead")]
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public bool? NetworkFeeDisabled
|
||||
|
|
14
BTCPayServer/Models/StoreViewModels/IntegrationsViewModel.cs
Normal file
14
BTCPayServer/Models/StoreViewModels/IntegrationsViewModel.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static BTCPayServer.Data.StoreBlob;
|
||||
|
||||
namespace BTCPayServer.Models.StoreViewModels
|
||||
{
|
||||
public class IntegrationsViewModel
|
||||
{
|
||||
public ShopifyDataHolder Shopify { get; set; }
|
||||
}
|
||||
}
|
|
@ -36,6 +36,23 @@ namespace BTCPayServer.Services.Shopify
|
|||
_httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + bearer);
|
||||
}
|
||||
|
||||
private HttpRequestMessage createRequest(string shopNameInUrl, HttpMethod method, string action)
|
||||
{
|
||||
var url = $"https://{shopNameInUrl}.myshopify.com/admin/api/2020-07/" + action;
|
||||
|
||||
var req = new HttpRequestMessage(method, url);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
private async Task<string> sendRequest(HttpRequestMessage req)
|
||||
{
|
||||
using var resp = await _httpClient.SendAsync(req);
|
||||
|
||||
var strResp = await resp.Content.ReadAsStringAsync();
|
||||
return strResp;
|
||||
}
|
||||
|
||||
public async Task<dynamic> TransactionsList(string orderId)
|
||||
{
|
||||
var req = createRequest(_creds.ShopName, HttpMethod.Get, $"orders/{orderId}/transactions.json");
|
||||
|
@ -58,21 +75,14 @@ namespace BTCPayServer.Services.Shopify
|
|||
return JObject.Parse(strResp);
|
||||
}
|
||||
|
||||
private HttpRequestMessage createRequest(string shopNameInUrl, HttpMethod method, string action)
|
||||
public async Task<int> OrdersCount()
|
||||
{
|
||||
var url = $"https://{shopNameInUrl}.myshopify.com/admin/api/2020-07/" + action;
|
||||
var req = createRequest(_creds.ShopName, HttpMethod.Get, $"orders/count.json");
|
||||
var strResp = await sendRequest(req);
|
||||
|
||||
var req = new HttpRequestMessage(method, url);
|
||||
dynamic parsed = JObject.Parse(strResp);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
private async Task<string> sendRequest(HttpRequestMessage req)
|
||||
{
|
||||
using var resp = await _httpClient.SendAsync(req);
|
||||
|
||||
var strResp = await resp.Content.ReadAsStringAsync();
|
||||
return strResp;
|
||||
return parsed.count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
87
BTCPayServer/Views/Stores/Integrations.cshtml
Normal file
87
BTCPayServer/Views/Stores/Integrations.cshtml
Normal file
|
@ -0,0 +1,87 @@
|
|||
@using static BTCPayServer.Data.StoreBlob
|
||||
@model IntegrationsViewModel
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Integrations, "Integrations");
|
||||
}
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
|
||||
@if (!ViewContext.ModelState.IsValid)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form method="post">
|
||||
<h4 class="mb-3">Shopify</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Shopify.ShopName"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#checkout-page-themes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<input asp-for="Shopify.ShopName" class="form-control" />
|
||||
<span asp-validation-for="Shopify.ShopName" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Shopify.ApiKey"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#checkout-page-themes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<input asp-for="Shopify.ApiKey" class="form-control" />
|
||||
<span asp-validation-for="Shopify.ApiKey" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Shopify.Password"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#checkout-page-themes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<input asp-for="Shopify.Password" class="form-control" />
|
||||
<span asp-validation-for="Shopify.Password" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Shopify.SharedSecret"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#checkout-page-themes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<input asp-for="Shopify.SharedSecret" class="form-control" />
|
||||
<span asp-validation-for="Shopify.SharedSecret" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
@if (Model.Shopify?.CredentialsValid == false)
|
||||
{
|
||||
<button name="command" type="submit" class="btn btn-primary" value="ShopifySaveCredentials">Save Credentials</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button name="command" type="submit" class="btn btn-error btn-sm" value="ShopifyClearCredentials">Clear Credentials</button>
|
||||
}
|
||||
|
||||
@if (Model.Shopify?.CredentialsValid == true)
|
||||
{
|
||||
var shopify = Model.Shopify;
|
||||
<br /><br />
|
||||
<h4 class="mb-3">Shopify Operations</h4>
|
||||
|
||||
if (!shopify.IntegratedAt.HasValue)
|
||||
{
|
||||
<button name="command" type="submit" class="btn btn-primary" value="ShopifyIntegrate">Integrate Shopify Order Paid Marking</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>
|
||||
Orders on <b>@shopify.ShopName</b>.myshopify.com will be marked as paid on successful invoice payment.
|
||||
Started: @shopify.IntegratedAt.Value.ToBrowserDate()
|
||||
</p>
|
||||
<p></p>
|
||||
}
|
||||
}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@await Html.PartialAsync("_ValidationScriptsPartial")
|
||||
}
|
Loading…
Add table
Reference in a new issue