@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\API;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Controllers\API\WeChatPayController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class DemoController extends Controller
|
||||||
|
{
|
||||||
|
public function pay_back()
|
||||||
|
{
|
||||||
|
$input = file_get_contents('php://input');
|
||||||
|
file_put_contents(base_path() . '/storage/app/pay/pay_back.txt', urldecode($input));
|
||||||
|
return [
|
||||||
|
'code' => 'SUCCESS',
|
||||||
|
'message' => '成功',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay(Request $request)
|
||||||
|
{
|
||||||
|
$openid = $request->post('openid');
|
||||||
|
$total = $request->post('total');
|
||||||
|
$wcp = new WeChatPayController();
|
||||||
|
$wcp->builder([
|
||||||
|
'appid' => 'wx0d92d2990ec16a55',
|
||||||
|
'pem_path' => base_path() . '/storage/app/pay/key.pem',
|
||||||
|
'cer_path' => base_path() . '/storage/app/pay/crt.pem',
|
||||||
|
'cer_num' => '3CE37188EBCFBBEB800B0E1C69B360F05A3E80CD',
|
||||||
|
'mchid' => '1638739772',
|
||||||
|
'v3' => 'AVPV7NxK8cC2RvRrrwdTqUG9YbQXQe3w',
|
||||||
|
]);
|
||||||
|
$out_trade_no = date('Ymd') . time() . rand(10, 99);
|
||||||
|
$pay = $wcp->create([
|
||||||
|
'description' => '体检预约',
|
||||||
|
'out_trade_no' => $out_trade_no,
|
||||||
|
'notify_url' => 'https://api.hainan2024.sa0.online/api/Demo/pay_back',
|
||||||
|
'total' => $total,
|
||||||
|
'openid' => $openid
|
||||||
|
]);
|
||||||
|
|
||||||
|
return \Yz::Return(true, '获取成功', [
|
||||||
|
'pay' => $pay
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\API;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use WeChatPay\Builder;
|
||||||
|
use WeChatPay\Crypto\AesGcm;
|
||||||
|
use WeChatPay\Crypto\Rsa;
|
||||||
|
use WeChatPay\Formatter;
|
||||||
|
use WeChatPay\Util\PemUtil;
|
||||||
|
|
||||||
|
class WeChatPayController extends Controller
|
||||||
|
{
|
||||||
|
public static $mp_instance = false;
|
||||||
|
public static $mp_config = false;
|
||||||
|
|
||||||
|
public function callback($input, $header, $apiv3Key, $pem)
|
||||||
|
{
|
||||||
|
$inWechatpaySignature = $header['wechatpay-signature'][0];
|
||||||
|
$inWechatpayTimestamp = $header['wechatpay-timestamp'][0];
|
||||||
|
$inWechatpaySerial = $header['wechatpay-serial'][0];
|
||||||
|
$inWechatpayNonce = $header['wechatpay-nonce'][0];
|
||||||
|
$inBody = $input;
|
||||||
|
$platformPublicKeyInstance = Rsa::from($pem, Rsa::KEY_TYPE_PUBLIC);
|
||||||
|
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
|
||||||
|
// $verifiedStatus = Rsa::verify(
|
||||||
|
// Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
|
||||||
|
// $inWechatpaySignature,
|
||||||
|
// $platformPublicKeyInstance
|
||||||
|
// );
|
||||||
|
// if ($timeOffsetStatus && $verifiedStatus) {
|
||||||
|
if ($timeOffsetStatus) {
|
||||||
|
$inBodyArray = (array)json_decode($inBody, true);
|
||||||
|
['resource' => [
|
||||||
|
'ciphertext' => $ciphertext,
|
||||||
|
'nonce' => $nonce,
|
||||||
|
'associated_data' => $aad
|
||||||
|
]] = $inBodyArray;
|
||||||
|
$inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
|
||||||
|
return (array)json_decode($inBodyResource, true);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function builder($config)
|
||||||
|
{
|
||||||
|
self::$mp_config = $config;
|
||||||
|
$merchantPrivateKeyFilePath = 'file://' . self::$mp_config['pem_path'];
|
||||||
|
$platformCertificateFilePath = 'file://' . self::$mp_config['cer_path'];
|
||||||
|
$merchantId = self::$mp_config['mchid'];
|
||||||
|
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
|
||||||
|
self::$mp_config['pem_key'] = $merchantPrivateKeyInstance;
|
||||||
|
$merchantCertificateSerial = self::$mp_config['cer_num'];
|
||||||
|
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
|
||||||
|
$platformCertificateSerial = self::$mp_config['v3'];
|
||||||
|
self::$mp_instance = Builder::factory([
|
||||||
|
'mchid' => $merchantId,
|
||||||
|
'serial' => $merchantCertificateSerial,
|
||||||
|
'privateKey' => $merchantPrivateKeyInstance,
|
||||||
|
'certs' => [
|
||||||
|
$platformCertificateSerial => $platformPublicKeyInstance,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refund($config)
|
||||||
|
{
|
||||||
|
$res = false;
|
||||||
|
try {
|
||||||
|
$resp = self::$mp_instance
|
||||||
|
->v3->refund->domestic->refunds
|
||||||
|
->post([
|
||||||
|
'json' => [
|
||||||
|
'transaction_id' => $config['transaction_id'],
|
||||||
|
'out_refund_no' => $config['out_refund_no'],
|
||||||
|
'amount' => [
|
||||||
|
'refund' => $config['total'],
|
||||||
|
'total' => $config['total'],
|
||||||
|
'currency' => 'CNY',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$res = json_decode($resp->getBody(), true);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||||||
|
$r = $e->getResponse();
|
||||||
|
$res = json_decode($r->getBody(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create($config)
|
||||||
|
{
|
||||||
|
$res = false;
|
||||||
|
try {
|
||||||
|
$post_data = [
|
||||||
|
'appid' => self::$mp_config['appid'],
|
||||||
|
'mchid' => self::$mp_config['mchid'],
|
||||||
|
'description' => $config['description'],
|
||||||
|
'out_trade_no' => $config['out_trade_no'],
|
||||||
|
'notify_url' => $config['notify_url'],
|
||||||
|
'amount' => [
|
||||||
|
'total' => $config['total'],
|
||||||
|
],
|
||||||
|
'payer' => [
|
||||||
|
'openid' => $config['openid']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$resp = self::$mp_instance
|
||||||
|
->v3->pay->transactions->jsapi
|
||||||
|
->post([
|
||||||
|
'json' => $post_data,
|
||||||
|
]);
|
||||||
|
$res = json_decode($resp->getBody(), true);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||||||
|
$r = $e->getResponse();
|
||||||
|
$res = json_decode($r->getBody(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$params = [
|
||||||
|
'appId' => self::$mp_config['appid'],
|
||||||
|
'timeStamp' => (string)time(),
|
||||||
|
'nonceStr' => self::nonce(),
|
||||||
|
'package' => 'prepay_id=' . $res['prepay_id'],
|
||||||
|
];
|
||||||
|
$params += ['paySign' => Rsa::sign(
|
||||||
|
Formatter::joinedByLineFeed(...array_values($params)),
|
||||||
|
self::$mp_config['pem_key']
|
||||||
|
), 'signType' => 'RSA'];
|
||||||
|
return [
|
||||||
|
'appid' => $params['appId'],
|
||||||
|
'timestamp' => $params['timeStamp'],
|
||||||
|
'nonce_str' => $params['nonceStr'],
|
||||||
|
'package' => $params['package'],
|
||||||
|
'pay_sign' => $params['paySign'],
|
||||||
|
'sign_type' => $params['signType'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function check($out_trade_no)
|
||||||
|
{
|
||||||
|
$res = false;
|
||||||
|
try {
|
||||||
|
$resp = self::$mp_instance
|
||||||
|
->v3->pay->transactions->outTradeNo->_out_trade_no_
|
||||||
|
->get([
|
||||||
|
'query' => ['mchid' => self::$mp_config['mchid']],
|
||||||
|
'out_trade_no' => (string)$out_trade_no,
|
||||||
|
]);
|
||||||
|
$res = json_decode($resp->getBody(), true);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||||||
|
$r = $e->getResponse();
|
||||||
|
$res = json_decode($r->getBody(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function nonce($l = 16)
|
||||||
|
{
|
||||||
|
$charts = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz0123456789";
|
||||||
|
$max = strlen($charts) - 1;
|
||||||
|
$noncestr = "";
|
||||||
|
for ($i = 0; $i < $l; $i++) {
|
||||||
|
$noncestr .= $charts[rand(0, $max)];
|
||||||
|
}
|
||||||
|
return $noncestr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,65 +1,69 @@
|
|||||||
{
|
{
|
||||||
"name": "laravel/laravel",
|
"name": "laravel/laravel",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"description": "The Laravel Framework.",
|
"description": "The Laravel Framework.",
|
||||||
"keywords": ["framework", "laravel"],
|
"keywords": [
|
||||||
"license": "MIT",
|
"framework",
|
||||||
"require": {
|
"laravel"
|
||||||
"php": "^7.3|^8.0",
|
],
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"license": "MIT",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"require": {
|
||||||
"laravel/framework": "^8.75",
|
"php": "^7.3|^8.0",
|
||||||
"laravel/sanctum": "^2.11",
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"laravel/tinker": "^2.5"
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
},
|
"laravel/framework": "^8.75",
|
||||||
"require-dev": {
|
"laravel/sanctum": "^2.11",
|
||||||
"facade/ignition": "^2.5",
|
"laravel/tinker": "^2.5",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"wechatpay/wechatpay": "^1.4"
|
||||||
"laravel/sail": "^1.0.1",
|
},
|
||||||
"mockery/mockery": "^1.4.4",
|
"require-dev": {
|
||||||
"nunomaduro/collision": "^5.10",
|
"facade/ignition": "^2.5",
|
||||||
"phpunit/phpunit": "^9.5.10"
|
"fakerphp/faker": "^1.9.1",
|
||||||
},
|
"laravel/sail": "^1.0.1",
|
||||||
"autoload": {
|
"mockery/mockery": "^1.4.4",
|
||||||
"classmap": [
|
"nunomaduro/collision": "^5.10",
|
||||||
"app/Lib"
|
"phpunit/phpunit": "^9.5.10"
|
||||||
],
|
},
|
||||||
"psr-4": {
|
"autoload": {
|
||||||
"App\\": "app/",
|
"classmap": [
|
||||||
"Database\\Factories\\": "database/factories/",
|
"app/Lib"
|
||||||
"Database\\Seeders\\": "database/seeders/"
|
],
|
||||||
}
|
"psr-4": {
|
||||||
},
|
"App\\": "app/",
|
||||||
"autoload-dev": {
|
"Database\\Factories\\": "database/factories/",
|
||||||
"psr-4": {
|
"Database\\Seeders\\": "database/seeders/"
|
||||||
"Tests\\": "tests/"
|
}
|
||||||
}
|
},
|
||||||
},
|
"autoload-dev": {
|
||||||
"scripts": {
|
"psr-4": {
|
||||||
"post-autoload-dump": [
|
"Tests\\": "tests/"
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
}
|
||||||
"@php artisan package:discover --ansi"
|
},
|
||||||
],
|
"scripts": {
|
||||||
"post-update-cmd": [
|
"post-autoload-dump": [
|
||||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
],
|
"@php artisan package:discover --ansi"
|
||||||
"post-root-package-install": [
|
],
|
||||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
"post-update-cmd": [
|
||||||
],
|
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
||||||
"post-create-project-cmd": [
|
],
|
||||||
"@php artisan key:generate --ansi"
|
"post-root-package-install": [
|
||||||
]
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
},
|
],
|
||||||
"extra": {
|
"post-create-project-cmd": [
|
||||||
"laravel": {
|
"@php artisan key:generate --ansi"
|
||||||
"dont-discover": []
|
]
|
||||||
}
|
},
|
||||||
},
|
"extra": {
|
||||||
"config": {
|
"laravel": {
|
||||||
"optimize-autoloader": true,
|
"dont-discover": []
|
||||||
"preferred-install": "dist",
|
}
|
||||||
"sort-packages": true
|
},
|
||||||
},
|
"config": {
|
||||||
"minimum-stability": "dev",
|
"optimize-autoloader": true,
|
||||||
"prefer-stable": true
|
"preferred-install": "dist",
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
import{$ as a,g as t,e,s as i,f as n,h as o}from"./index-DqaBDANc.js";const s=a.token;function l(){return t(s)}const d=e("counter",{state:()=>({api_map:{},count:0,loading:0}),actions:{loadingStart(){this.loading++},loadingDone(){this.loading--,this.loading<0&&(this.loading=0)}}}),p=async({url:a,data:t={}},e)=>{const s=d();let p={};if("delete_token"in e&&e.delete_token)p.Authorization&&delete p.Authorization;else{const a=l()?l():"";p.Authorization="Bearer "+a}"delete_appid"in e&&e.delete_appid?t.UNIAPP_APPID&&delete t.UNIAPP_APPID:t.UNIAPP_APPID=e.appid,"delete_apptype"in e&&e.delete_apptype?t.UNIAPP_APPTYPE&&delete t.UNIAPP_APPTYPE:t.UNIAPP_APPTYPE=e.app_type,e.loading&&(s.loadingStart(),1===s.loading&&i({title:e.loading_text}));const r=await n({url:a,method:"POST",data:t,header:p});return e.loading&&(s.loadingDone(),0===s.loading&&o()),r&&""!=r.data?r.data:(uni.$lu.toast("请求发生错误"),!1)};a.config.api_map_url,a.config.base_assets_url;const r=async(t,e={},i={})=>{const n={...a,...i},o=d();if(!(t in o.api_map)){const a=await p({url:n.config.api_map_url},n);if(!a.status)return uni.$lu.toast("获取接口失败"),!1;o.api_map=a.data.list}return t in o.api_map?await p({url:o.api_map[t],data:e},n):(uni.$lu.toast(`接口不存在 [${t}]`),!1)},u=(t,e,i={},n=(()=>{}))=>{if(t){const o={...a,...i};if(t.status!=o.success_code)return uni.$lu.toast(t.message),void n();e()}};export{r as $,u as a};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{c as a,w as s,i as o,o as e,a as t,b as n}from"./index-DqaBDANc.js";import"./index.BjiQWzit.js";const r={__name:"combo",setup:r=>(r,l)=>{const m=o;return e(),a(m,null,{default:s((()=>[t(" Combo "),n(m,{class:"blank_wrapper"})])),_:1})}};export{r as default};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{c as a,w as s,i as e,o as n,a as d,b as t,n as l,d as r}from"./index-DqaBDANc.js";import"./index.BjiQWzit.js";const i={__name:"index",setup:i=>(i,o)=>{const p=r,u=e;return n(),a(u,null,{default:s((()=>[d(" Index "),t(p,{onClick:o[0]||(o[0]=a=>{l({url:"/pages/main/dev/dev"})})},{default:s((()=>[d("开发测试")])),_:1}),t(u,{class:"blank_wrapper"})])),_:1})}};export{i as default};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{c as a,w as s,i as r,o as e,a as t,b as n}from"./index-DqaBDANc.js";import"./index.BjiQWzit.js";const o={__name:"order",setup:o=>(o,d)=>{const l=r;return e(),a(l,null,{default:s((()=>[t(" Order "),n(l,{class:"blank_wrapper"})])),_:1})}};export{o as default};
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/h5/assets/uni.943b8fef.css">
|
||||||
|
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script><title>海南现代妇女儿童医院</title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
<script type="module" crossorigin src="/h5/assets/index-DqaBDANc.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/h5/assets/index-BPRTVkjj.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 401 B |
|
After Width: | Height: | Size: 470 B |
|
After Width: | Height: | Size: 511 B |
|
After Width: | Height: | Size: 476 B |
|
After Width: | Height: | Size: 472 B |
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 365 B |
|
After Width: | Height: | Size: 587 B |
|
After Width: | Height: | Size: 565 B |
@ -0,0 +1,20 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "customicons"; /* Project id 2878519 */
|
||||||
|
src:url('/static/customicons.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.customicons {
|
||||||
|
font-family: "customicons" !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youxi:before {
|
||||||
|
content: "\e60e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.wenjian:before {
|
||||||
|
content: "\e60f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.zhuanfa:before {
|
||||||
|
content: "\e610";
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 4.1 KiB |