diff --git a/miniapp/config/index.js b/miniapp/config/index.js index 7794e45..6bdbd8d 100644 --- a/miniapp/config/index.js +++ b/miniapp/config/index.js @@ -23,7 +23,7 @@ const ENV = { } // 当前环境 - 开发时使用 development,打包时改为 production -const CURRENT_ENV = 'development' +const CURRENT_ENV = 'production' // 导出配置 export const config = { diff --git a/nginx/html_app.zpc-xy.com.conf b/nginx/html_app.zpc-xy.com.conf new file mode 100644 index 0000000..9391132 --- /dev/null +++ b/nginx/html_app.zpc-xy.com.conf @@ -0,0 +1,112 @@ +server +{ + listen 80; + listen 443 ssl; + listen 443 quic; + http2 on; + server_name app.zpc-xy.com; + index index.html index.htm default.htm default.html; + root /www/wwwroot/app.zpc-xy.com; + include /www/server/panel/vhost/nginx/extension/app.zpc-xy.com/*.conf; + #CERT-APPLY-CHECK--START + # 用于SSL证书申请时的文件验证相关配置 -- 请勿删除并保持这段设置在优先级高的位置 + include /www/server/panel/vhost/nginx/well-known/app.zpc-xy.com.conf; + #CERT-APPLY-CHECK--END + + #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则 + #error_page 404/404.html; + ssl_certificate /www/server/panel/vhost/cert/app.zpc-xy.com/fullchain.pem; + ssl_certificate_key /www/server/panel/vhost/cert/app.zpc-xy.com/privkey.pem; + ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; + ssl_prefer_server_ciphers on; + ssl_session_tickets on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + add_header Strict-Transport-Security "max-age=31536000"; + add_header Alt-Svc 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"'; + error_page 497 https://$host$request_uri; + + #SSL-END + + #ERROR-PAGE-START 错误页配置,可以注释、删除或修改 + #error_page 404 /404.html; + #error_page 502 /502.html; + #ERROR-PAGE-END + + #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效 + include /www/server/panel/vhost/rewrite/html_app.zpc-xy.com.conf; + #REWRITE-END + + #跨域处理 + add_header Access-Control-Allow-Origin * always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, PATCH" always; + add_header Access-Control-Allow-Headers $http_access_control_request_headers always; + add_header Access-Control-Max-Age 86400 always; + add_header Access-Control-Allow-Credentials true always; + + #禁止访问的文件或目录 + location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) + { + return 404; + } + + #子目录API转发规则 - 用^~确保优先级最高 + location ^~ /xyqj/api/ { + #处理OPTIONS预检请求 + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin * always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, PATCH" always; + add_header Access-Control-Allow-Headers $http_access_control_request_headers always; + add_header Access-Control-Max-Age 86400 always; + add_header Access-Control-Allow-Credentials true always; + return 204; + } + + proxy_pass http://192.168.195.15:2802/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + + #重写响应体中的绝对路径,添加/xyqj/api前缀 + sub_filter '"url":"/' '"url":"/xyqj/api/'; + sub_filter 'href="/' 'href="/xyqj/api/'; + sub_filter 'src="/' 'src="/xyqj/api/'; + sub_filter_once off; + + #转发时的跨域处理 + add_header Access-Control-Allow-Origin * always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, PATCH" always; + add_header Access-Control-Allow-Headers $http_access_control_request_headers always; + add_header Access-Control-Max-Age 86400 always; + add_header Access-Control-Allow-Credentials true always; + } + + #一键申请SSL证书验证目录相关设置 + location ~ \.well-known{ + allow all; + } + + #禁止在证书验证目录放入敏感文件 + if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) { + return 403; + } + + location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$ + { + expires 30d; + error_log /dev/null; + access_log /dev/null; + } + + location ~ .*\\.(js|css)?$ + { + expires 12h; + error_log /dev/null; + access_log /dev/null; + } + access_log /www/wwwlogs/app.zpc-xy.com.log; + error_log /www/wwwlogs/app.zpc-xy.com.error.log; +} \ No newline at end of file diff --git a/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs b/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs index fbf338b..62cc0aa 100644 --- a/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs +++ b/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs @@ -430,7 +430,34 @@ public class WeChatService : IWeChatService private string SignWithPrivateKey(string message) { using var rsa = RSA.Create(); - rsa.ImportFromPem(_options.Pay.PrivateKey); + + // 优先从文件读取,如果文件不存在则从配置读取 + string privateKeyPem; + if (!string.IsNullOrEmpty(_options.Pay.PrivateKey) && _options.Pay.PrivateKey.StartsWith("-----BEGIN")) + { + // 从配置中读取,处理转义的换行符 + privateKeyPem = _options.Pay.PrivateKey.Replace("\\n", "\n"); + } + else + { + // 从文件读取 + var keyPath = Path.Combine(AppContext.BaseDirectory, "apiclient_key.pem"); + if (!File.Exists(keyPath)) + { + throw new FileNotFoundException($"私钥文件不存在: {keyPath}"); + } + privateKeyPem = File.ReadAllText(keyPath); + } + + try + { + rsa.ImportFromPem(privateKeyPem.AsSpan()); + } + catch (Exception ex) + { + _logger.LogError(ex, "导入私钥失败,私钥内容长度: {Length}", privateKeyPem.Length); + throw; + } var data = Encoding.UTF8.GetBytes(message); var signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);