initial commit 2

This commit is contained in:
equippedcoding-master
2025-09-17 15:19:57 -05:00
parent e2c98790b2
commit 1c59875b8a
55391 changed files with 15 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
########## BEGIN RECOMMENDED RULES (COMMENT OUT OR UNCOMMENT AS NEEDED) ##########
### htaccess (https://github.com/delight-im/htaccess)
### Copyright (c) delight.im (https://www.delight.im/)
### Licensed under the MIT License (https://opensource.org/licenses/MIT)
<ifModule mod_headers.c>
# Prevent clickjacking (forbids framing by third-party sites)
Header set X-Frame-Options sameorigin
# Prevent content sniffing (MIME sniffing)
Header set X-Content-Type-Options nosniff
# Attempt to enable XSS filters in browsers, if available, and block reflected XSS
Header set X-XSS-Protection "1; mode=block"
# Cache media files for a month
<FilesMatch "\.(js|css|jpg|jpeg|png|svg|webp|gif|ico|ogg|mp4|webm)$">
Header set Cache-Control max-age=2629800
</FilesMatch>
# Remove response headers that provide no value but leak information
Header unset X-Powered-By
# Disable "ETag" headers so that browsers rely on the "Cache-Control" and "Expires" headers
Header unset ETag
</ifModule>
<IfModule mod_autoindex.c>
# Turn off directory listings for folders without default documents
Options -Indexes
</IfModule>
<IfModule mod_negotiation.c>
# Disable 'MultiViews' implicit filename pattern matches
Options -MultiViews
</IfModule>
# Serve "text/plain" and "text/html" documents as UTF-8 by default
AddDefaultCharset utf-8
# Disable "ETag" headers so that browsers rely on the "Cache-Control" and "Expires" headers
FileETag None
<ifModule mod_headers.c>
# Enable HTTP Strict Transport Security (HSTS) with a duration of six months (Uncomment 1 line below)
# Header set Strict-Transport-Security max-age=15778800
</ifModule>
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /v1/webhooks/index.php [L]
# Force 'www' (i.e. prefix the "bare" domain and all subdomains with 'www' through permanent redirects) (Uncomment 6 lines below)
# RewriteCond %{HTTP_HOST} !^$
# RewriteCond %{HTTP_HOST} !^www\. [NC]
# RewriteCond %{HTTPS}s ^on(s)|
# # RewriteCond %{REQUEST_SCHEME} ^http(s)|
# # RewriteCond %{SERVER_PORT}s ^443(s)|
# RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Force HTTPS (Uncomment 4 lines below)
# RewriteCond %{HTTPS} off
# # RewriteCond %{REQUEST_SCHEME} http
# # RewriteCond %{SERVER_PORT} !443
# RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
# Prevent access to non-minified CSS and JS (Uncomment 3 lines below)
# <FilesMatch "(?<!.min)\.(css|js)$">
# Require all denied
# </FilesMatch>
# Show a custom error document for "404 Not Found" errors (Uncomment 1 line below)
# ErrorDocument 404 /notFound.html
# Announce contact information for security issues (Uncomment 2 lines below)
# Header set X-Vulnerability-Disclosure "https://www.example.com/security"
# Header set X-Security-Contact "security@example.com"
########## END RECOMMENDED RULES ##########
########## BEGIN CUSTOM RULES (YOUR OWN RULES GO HERE) ##########
# Add your rules here ...
########## END CUSTOM RULES ##########
#<ifModule mod_rewrite.c>
# RewriteEngine On
# RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# RewriteBase /
# RewriteRule ^index\.php$ - [L]
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule . /v1/payments/index.php [L]
#</IfModule>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set timing-allow-origin "*"
# content-security-policy:

View File

@@ -0,0 +1,20 @@
<?php
$dir = dirname( __DIR__, 3 );
require $dir . "/admin/core/api/php/includes/init.php";
$router = new AppfactoryStudio\Core\Router();
$router->post('/stripe',[AppfactoryStudio\Plugins\Payments::class, 'webhook_stripe']);
$router->post('/paypal',[AppfactoryStudio\Plugins\Payments::class, 'webhook_paypal']);
// https://api.appfactory.studio/v1/modules/stripe/webhook
// https://api.appfactory.studio/v1/webhooks/stripe
// https://api-sandbox.appfactory.studio/v1/webhooks/stripe
echo $router->UrlResolve("/v1/webhooks", $_SERVER['REQUEST_URI'], strtolower($_SERVER['REQUEST_METHOD']));

View File

@@ -0,0 +1,574 @@
<?php
require_once dirname( __DIR__, 9 ) . "/portal/admin/core/api/php/includes/init.php";
require_once dirname( __DIR__, 9 ) . "/portal/admin/core/api/php/includes/functions.php";
require_once dirname( __DIR__, 9 ) . "/portal/admin/core/api/php/includes/libs/slim/vendor/autoload.php";
require_once dirname( __DIR__, 9 ) . "/portal/admin/core/api/php/includes/libs/di/vendor/autoload.php";
// /home/appfactorystudio/websites/www/admin/core/api/php/includes/libs/slim/vendor/autoload.php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use DI\Container;
use Stripe\Stripe;
if(Input::get("hellogfgdfg453545")){
// https://www.appfactory.studio/portal/admin/core/api/php/includes/services/payments/stripe/stripe_payments.php?hello=true
$manage_domain = GetManagedDomain();
EchoJsonObject($manage_domain);
}
# Stripe - Real Practice Mode
# pk_test_51S30kTJTsOSWtcD79lohqmoR82oCRRMoaLXt5Mp3w4IjY8aWe8DryZD9Jn0vjewY9LkrXpSl30WucTAv4Znknr1w00X4vLzqQT
# sk_test_51S30kTJTsOSWtcD7ax91Gua2pmkx113y769Ce5cKaMzwx9cFUQqB1z8Wzn4o8Yvv9yd80F3YrGUX5czO2q0pW50w007qSsYLrQ
function GetStripe($client_secret,$manage_domain){
\Stripe\Stripe::setAppInfo(
"stripe-samples/subscription-use-cases/fixed-price",
"0.0.1",
"https://github.com/stripe-samples/subscription-use-cases/fixed-price"
);
$stripe = new \Stripe\StripeClient([
'api_key' => $client_secret,
'stripe_version' => '2022-08-01',
]);
return $stripe;
}
if(Input::get('get_prices')){
$data = json_decode(Input::get('data'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data; //['json' => $data];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
// json.json.configuration.recurring.subscriptions[0].tiers
$tiers = $data['json']['configuration']['recurring']['subscriptions'][0]['tiers'];
$lookup_keys = [];
for ($i=0; $i < count($tiers); $i++) {
if($tiers[$i]["lookup_key"]=="_none_"){
continue;
}
array_push($lookup_keys,$tiers[$i]["lookup_key"]);
}
$pub_key = $data['_processor']['json']['client_id'];
$prices = $stripe->prices->all(['lookup_keys' => $lookup_keys]);
EchoJsonObject([
'publishableKey' => $pub_key,
'prices' => $prices->data,
'tiers' => $tiers,
'lookup_keys' => $lookup_keys
]);
}
if(Input::get('submit_payment')){
$data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
}
if(Input::get('create_customer')){
$data = json_decode(Input::get('data'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data['direct_payment'];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
// Create a new customer object
$customer = $stripe->customers->create([
'email' => $data['email']
]);
// Set a cookie for the customer to simulate authentication.
// In practice, store the Stripe Customer ID ($customer->id)
// in your database along side your user data.
// setcookie('customer', $customer->id, time()+60*60*24);
EchoJsonObject(['customer' => $customer]);
}
if(Input::get('get_customer')){
$data = json_decode(Input::get('data'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data['direct_payment'];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
// Create a new customer object
$customer = $stripe->customers->retrieve($data['customer_id']);
$subscription = $stripe->subscriptions->retrieve($data['subscription_id']);
\Stripe\Stripe::setApiKey($processor['json']['client_secret']);
$subscription = \Stripe\Subscription::retrieve([
'id' =>$subscription->id, // Replace with your subscription ID
'expand' => ['customer', 'latest_invoice.payment_intent'], // Expand customer and the payment_intent of the latest invoice
]);
$datetime = date('Y-m-d', $subscription->latest_invoice->lines->data[0]->period->end);
// $datetime = new DateTime();
EchoJsonObject([
"customer" => $customer,
"subscription" => $subscription,
"end" => $subscription->latest_invoice->lines->data[0]->period->end,
"start" => $subscription->latest_invoice->lines->data[0]->period->start,
"format" => $datetime
]);
}
if(Input::get('create_subscription')){
$data = json_decode(Input::get('data'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data['direct_payment'];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
# Simulates an authenticated user. In practice, you'll
# use the Stripe Customer ID of the authenticated user.
$customer_id = $data['customer'];
# The ID of a Price object in your Stripe account. In this
# sample, it's stored in the .env file and loaded from environment
# variables.
$price_id = $data['price_id'];
// Create the subscription.
$subscription = $stripe->subscriptions->create([
'customer' => $customer_id,
'items' => [[
'price' => $price_id,
]],
'payment_behavior' => 'default_incomplete',
'expand' => ['latest_invoice.payment_intent'],
]);
EchoJsonObject([
'subscription' => $subscription,
'subscriptionId' => $subscription->id,
'clientSecret' => $subscription->latest_invoice->payment_intent->client_secret
]);
}
if(Input::get('invoice-preview')){
$data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
$customer_id = $_COOKIE['customer'];
$subscription_id = $request->getQueryParam('subscriptionId');
$new_price_lookup_key = strtoupper($request->getQueryParam('newPriceLookupKey'));
$subscription = $stripe->subscriptions->retrieve($subscription_id);
$invoice = $stripe->invoices->upcoming([
'customer' => $customer_id,
'subscription' => $subscription_id,
'subscription_items' => [[
'id' => $subscription->items->data[0]->id,
'price' => getenv($new_price_lookup_key),
]],
]);
EchoJsonObject(['invoice' => $invoice]);
}
if(Input::get('cancel_subscription')){
$data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
$subscription = $stripe->subscriptions->cancel($body->subscriptionId);
EchoJsonObject(['subscription' => $subscription]);
}
if(Input::get('update_subscription')){
$data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
$new_price_id = getenv(strtoupper($body->newPriceLookupKey));
$subscription = $stripe->subscriptions->retrieve($body->subscriptionId);
$updatedSubscription = $stripe->subscriptions->update(
$body->subscriptionId, [
'items' => [[
'id' => $subscription->items->data[0]->id,
'price' => $new_price_id,
]],
]
);
EchoJsonObject(['subscription' => $updatedSubscription]);
}
if(Input::get('subscriptions')){
$data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
# Simulates an authenticated user. In practice, you'll
# use the Stripe Customer ID of the authenticated user.
$customer_id = $data['customer'];
$subscriptions = $stripe->subscriptions->all([
'customer' => $customer_id,
'status' => 'all',
'expand' => ['data.default_payment_method'],
]);
EchoJsonObject(['subscriptions' => $subscriptions]);
}
if(Input::get('update_customer')){
$data = json_decode(Input::get('data'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data['direct_payment'];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
$customer = $data["customer"];
$email = $data["email"];
try {
$customer = $stripe->customers->update(
$customer["id"], //'cus_YOUR_CUSTOMER_ID', // Replace with the actual customer ID
[
'email' => $email,
'description' => 'Updated customer email',
// 'metadata' => [
// 'order_id' => 'new_order_123',
// 'custom_field' => 'some_value'
// ],
// Add other parameters you want to update, e.g., 'default_source', 'invoice_settings'
]
);
// echo "Customer updated successfully: " . $customer->id;
EchoJsonObject(['message' => "success"]);
} catch (\Stripe\Exception\ApiErrorException $e) {
// Handle API errors (e.g., invalid customer ID, invalid parameters)
EchoJsonObject(['message' => $e->getMessage()]);
}
}
if(Input::get('apply_coupon')){
$data = json_decode(Input::get('direct_payment'), true);
$_POST["category"] = "processors";
$configuration = get_configuration_obj();
$one = $data; //['json' => $data];
$processor = DirectPaymentsSelectProcessor($one, $configuration);
$manage_domain = GetManagedDomain();
$stripe = GetStripe($processor['json']['client_secret'],$manage_domain);
$price_id = Input::get("price_id");
$code = Input::get("code");
// Create a new customer object
$customer = $stripe->customers->create();
try {
$promotionCodes = $stripe->promotionCodes->all([
'limit' => 10,
'code' => $code,
'active' => true,
]);
if (!empty($promotionCodes->data)) {
$promotionCode = $promotionCodes->data[0]; // Get the first matching promotion code
// echo "Promotion Code ID: " . $promotionCode->id . "\n";
// echo "Customer-facing Code: " . $promotionCode->code . "\n";
// echo "Coupon ID: " . $promotionCode->coupon->id . "\n";
// Access other properties as needed
// EchoJsonObject(["promo" => $promotionCodes]);
try {
$subscription = $stripe->subscriptions->create([
'customer' => $customer->id,
'items' => [
[
'price' => $price_id, // Replace with your price ID
'discounts' => [
[
'promotion_code' => $promotionCode->id, // Replace with your promotion code ID
],
],
],
],
'payment_behavior' => 'default_incomplete',
'expand' => ['latest_invoice.payment_intent'],
// 'discounts' => [['coupon' => $promotionCode->coupon->id]],
]);
// echo "Subscription created with promotion code: " . $subscription->id;
EchoJsonObject([
'subscriptions' => $subscription,
'customer' => $customer,
'promo' => $promotionCodes,
'clientSecret' => $subscription->latest_invoice->payment_intent->client_secret
]);
} catch (\Stripe\Exception\ApiErrorException $e) {
// echo "Error creating subscription: " . $e->getMessage();
EchoJsonResponse($e->getMessage());
}
} else {
// echo "Promotion code not found with the given customer-facing code.";
EchoJsonObject([
'message' => 'no code error 1',
'object' => $promotionCodes
]);
}
} catch (\Stripe\Exception\ApiErrorException $e) {
// echo "Error listing promotion codes: " . $e->getMessage();
EchoJsonObject(['message' => 'no code error 2', 'msg' => $e->getMessage(), 'data' => $processor]);
}
}
// stripe listen --forward-to https://www.appfactory.studio/portal/admin/core/api/php/includes/services/payments/stripe/stripe_payments.php?webhook=true --skip-verify
if(Input::get('webhook')){
sleep(3);
// $data = json_decode(Input::get('data'), true);
$manage_domain = GetManagedDomain();
// $stripe = GetStripe($data['_processor']['json']['client_secret'],$manage_domain);
if(is_dir("/mnt/node1/appfactorystudio/datainfo/stripe_payment_events")==false){
if (mkdir("/mnt/node1/appfactorystudio/datainfo/stripe_payment_events", 0777, true)) {}
}
\Stripe\Stripe::setAppInfo(
"stripe-samples/subscription-use-cases/fixed-price",
"0.0.1",
"https://github.com/stripe-samples/subscription-use-cases/fixed-price"
);
$stripe = new \Stripe\StripeClient([
'api_key' => "sk_test_51S30kTJTsOSWtcD7ax91Gua2pmkx113y769Ce5cKaMzwx9cFUQqB1z8Wzn4o8Yvv9yd80F3YrGUX5czO2q0pW50w007qSsYLrQ",
'stripe_version' => '2022-08-01',
]);
$requestHeaders = getallheaders();
$content = trim(file_get_contents("php://input"));
$decoded = json_decode($content, true);
Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile.txt",$decoded);
// Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile.txt",$requestHeaders);
$webhookSecret = "whsec_b14c84359ebe2d3414c82d52ee683b5fbc3fec44e596f897c8dc9b8fe49769c4";
// Parse the message body (and check the signature if possible)
if ($webhookSecret) {
try {
$event = \Stripe\Webhook::constructEvent(
$content,
$requestHeaders['Stripe-Signature'],
$webhookSecret
);
} catch (Exception $e) {
Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile.txt",['error' => $e->getMessage(), "header" => $requestHeaders['Stripe-Signature']]);
http_response_code(403);
return EchoJsonObject(['error' => $e->getMessage()]);
}
} else {
// $event = $request->getParsedBody();
}
$type = $event['type'];
$object = $event['data']['object'];
Utils_WriteFileJson("/mnt/node1/appfactorystudio/datainfo/stripe_payment_events/$type.json",$event);
Utils_WriteFileJson("/mnt/node1/appfactorystudio/datainfo/stripe_payment_events/$type.json",$event);
// Handle the event
// Review important events for Billing webhooks
// https://stripe.com/docs/billing/webhooks
switch ($type) {
case "charge.succeeded":
// sleep(5);
// Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile1.json",['help' => 'not working']);
$payment_intent = $object['payment_intent'];
$filepath = "/mnt/node1/appfactorystudio/datainfo/stripe_payment_action/$payment_intent-1.json";
if (file_exists($filepath)) {
$json = json_decode(file_get_contents($filepath),true);
$managed_domain = $json["managed_domain"];
$config1 = $json["config"];
$handler = $json["mail_handlers"];
$member = $json["member"];
$client_variables = $json["client_variables"];
for ($n=0; $n < count($client_variables); $n++) {
array_push($client_variables[$n], [
"name" => "card_last4",
"value" => $object["payment_method_details"]["card"]["last4"]
]);
array_push($client_variables[$n], [
"name" => "card_created",
"value" => $object["created"]
]);
array_push($client_variables[$n], [
"name" => "card_curreny",
"value" => $object["currency"]
]);
array_push($client_variables[$n], [
"name" => "card_brand",
"value" => $object["payment_method_details"]["card"]["brand"]
]);
array_push($client_variables[$n], [
"name" => "card_country",
"value" => $object["payment_method_details"]["card"]["country"]
]);
}
$json["client_variables"] = $client_variables;
Utils_WriteFileJson($filepath,$json);
// Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile777.json",["handle" => $handler]);
// Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile4.json",["handle" => $client_variables]);
$integration = GetActiveEmailIntegration($config1);
$mail_handler = array_shift($json["mail_handlers"]);
SendEmailBuildIntegration(
$mail_handler,
$client_variables,
$integration,
$config1,
$managed_domain,
function($resp){
Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile4.json",["handle" => $resp]);
});
} else {
Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile1.json",[
'error' => 'file does not exit',
'file' => $filepath
]);
}
break;
case 'invoice_payment.paid':
$payment_intent = $object['payment']['payment_intent'];
$filename_save = "/mnt/node1/appfactorystudio/datainfo/stripe_payment_action/$payment_intent-1.json";
break;
case 'invoice.paid':
if ($object['billing_reason'] == 'subscription_create') {
// The subscription automatically activates after successful payment
// Set the payment method used to pay the first invoice
// as the default payment method for that subscription
$subscription_id = $object['subscription'];
$payment_intent_id = $object['payment_intent'];
# Retrieve the payment intent used to pay the subscription
$payment_intent = $stripe->paymentIntents->retrieve(
$payment_intent_id,
[]
);
try {
$stripe->subscriptions->update(
$subscription_id,
['default_payment_method' => $payment_intent->payment_method],
);
// $logger->info('Default payment method set for subscription:' . $payment_intent->payment_method);
} catch (Exception $e) {
// $logger->info($e->getMessage());
// $logger->info('Falied to update the default payment method for subscription: ' . $subscription_id);
}
};
// database to reference when a user accesses your service to avoid hitting rate
// limits.
// $logger->info('Invoice paid: ' . $event->id);
break;
case 'invoice.payment_failed':
// If the payment fails or the customer does not have a valid payment method,
// an invoice.payment_failed event is sent, the subscription becomes past_due.
// Use this webhook to notify your user that their payment has
// failed and to retrieve new card details.
// $logger->info('Invoice payment failed: ' . $event->id);
break;
case 'invoice.finalized':
// If you want to manually send out invoices to your customers
// or store them locally to reference to avoid hitting Stripe rate limits.
// $logger->info('Invoice finalized: ' . $event->id);
break;
case 'customer.subscription.deleted':
// handle subscription cancelled automatically based
// upon your subscription settings. Or if the user
// cancels it.
// $logger->info('Subscription canceled: ' . $event->id);
break;
// ... handle other event types
default:
// Unhandled event type
}
Utils_WriteFileJson("/mnt/node1/appfactorystudio/tmp/tailfile.txt",['error' => $event]);
http_response_code(200);
EchoJsonObject(['status' => 'success']);
}