diff --git a/app/Controller/InquiryController.php b/app/Controller/InquiryController.php index 5724cca..a9df25a 100644 --- a/app/Controller/InquiryController.php +++ b/app/Controller/InquiryController.php @@ -4,6 +4,8 @@ namespace App\Controller; use App\Request\InquiryRequest; use App\Services\InquiryService; +use Extend\Wechat\WechatPay; +use Hyperf\Snowflake\IdGeneratorInterface; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Http\Message\ResponseInterface; @@ -49,4 +51,22 @@ class InquiryController extends AbstractController $data = $InquiryService->getPatientInquiryCase(); return $this->response->json($data); } + + public function addInquiryOrderTest(){ + $WechatPay = new WechatPay(2); + + $generator = $this->container->get(IdGeneratorInterface::class); + + $out_trade_no = $generator->generate(); + dump($out_trade_no); + + // 获取jsapi的prepay_id + $total = 100; + $openid = "o9gYG441zEAHuYoNX7lwFKiQBzKE"; + $result = $WechatPay->getJsapiPrepayId($out_trade_no,$total,$openid); + + // 获取小程序支付配置 + $config = $WechatPay->getAppletsPayConfig($result['prepay_id']); + dump($config); + } } \ No newline at end of file diff --git a/app/Controller/PayController.php b/app/Controller/PayController.php new file mode 100644 index 0000000..071bda4 --- /dev/null +++ b/app/Controller/PayController.php @@ -0,0 +1,17 @@ +request->all(); + Log::getInstance()->info(json_encode($request_params,JSON_UNESCAPED_UNICODE)); + } +} \ No newline at end of file diff --git a/app/Request/InquiryRequest.php b/app/Request/InquiryRequest.php index fdcd018..c8587f1 100644 --- a/app/Request/InquiryRequest.php +++ b/app/Request/InquiryRequest.php @@ -28,6 +28,7 @@ class InquiryRequest extends FormRequest 'weight', 'inquiry_type', // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药) 'inquiry_mode', // 订单问诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) + 'client_type', // 客户端类型(1:手机 2:电脑) ], ]; @@ -55,6 +56,7 @@ class InquiryRequest extends FormRequest 'is_allergy_history' => ['sometimes','numeric','min:0','max:1'], 'is_family_history' => ['sometimes','numeric','min:0','max:1'], 'is_pregnant' => ['sometimes','numeric','min:0','max:1'], + 'client_type' => 'required|integer|min:1|max:2', ]; } @@ -87,6 +89,10 @@ class InquiryRequest extends FormRequest 'is_pregnant.numeric' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'is_pregnant.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), 'is_pregnant.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'client_type.required' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'client_type.integer' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'client_type.min' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), + 'client_type.max' => HttpEnumCode::getMessage(HttpEnumCode::CLIENT_HTTP_ERROR), ]; } } diff --git a/app/Services/InquiryService.php b/app/Services/InquiryService.php index e345438..6a4eac5 100644 --- a/app/Services/InquiryService.php +++ b/app/Services/InquiryService.php @@ -15,6 +15,7 @@ use App\Model\PatientFamilyPersonal; use App\Model\Product; use App\Model\UserDoctor; use App\Utils\PcreMatch; +use Extend\Wechat\WechatPay; use Hyperf\Amqp\Producer; use Hyperf\DbConnection\Db; use Hyperf\Snowflake\IdGeneratorInterface; @@ -99,6 +100,14 @@ class InquiryService extends BaseService $CouponService = new CouponService(); $user_coupon = $CouponService->getUserUsableCouponOne($user_info['user_id'], $request_params['inquiry_type']); + // 确定支付渠道 + // 支付渠道(1:小程序支付 2:微信扫码支付) + if ($request_params['inquiry_pay_channel'] == 1){ + $inquiry_pay_channel = 1; + }elseif ($request_params['inquiry_pay_channel'] == 2){ + $inquiry_pay_channel = 2; + } + Db::beginTransaction(); $generator = $this->container->get(IdGeneratorInterface::class); @@ -117,6 +126,7 @@ class InquiryService extends BaseService $data['inquiry_type'] = $request_params['inquiry_type']; $data['inquiry_mode'] = $request_params['inquiry_mode']; $data['inquiry_status'] = 1;// 1:待支付 + $data['inquiry_pay_channel'] = $inquiry_pay_channel ?? 0;// 支付渠道(1:小程序支付 2:微信扫码支付) $data['inquiry_no'] = $generator->generate();// 订单编号 $data['amount_total'] = $inquiry_price;// 订单金额 $data['payment_amount_total'] = $payment_amount_total;// 实际付款金额 @@ -230,19 +240,33 @@ class InquiryService extends BaseService } } - // 增加至退款延迟队列 - $data = array(); - $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; + // 发起支付 + $WechatPay = new WechatPay(1); - $message = new CancelUnpayOrdersDelayDirectProducer($data); - $message->setDelayMs(60 * 30 * 1000); - $producer = $this->container->get(Producer::class) ; - $res = $producer->produce($message); - if(!$res){ + // 获取预支付交易会话标识 + $total = $inquiry_price * 100; + $prepay = $WechatPay->getJsapiPrepayId($order_inquiry['inquiry_no'],$total,$user_info['open_id']); + if (empty($prepay)){ Db::rollBack(); return fail(HttpEnumCode::SERVER_ERROR, "订单创建失败"); } + // 获取小程序支付配置 + $pay_config = $WechatPay->getAppletsPayConfig($prepay['prepay_id']); + + // 增加至退款延迟队列 +// $data = array(); +// $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; +// +// $message = new CancelUnpayOrdersDelayDirectProducer($data); +// $message->setDelayMs(60 * 30 * 1000); +// $producer = $this->container->get(Producer::class) ; +// $res = $producer->produce($message); +// if(!$res){ +// Db::rollBack(); +// return fail(HttpEnumCode::SERVER_ERROR, "订单创建失败"); +// } + Db::commit(); } catch (\Exception $e) { Db::rollBack(); @@ -255,6 +279,7 @@ class InquiryService extends BaseService $result['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; // 订单主键id $result['created_at'] = date('Y-m-d H:i:s',strtotime($order_inquiry['created_at'])); // 创建时间 $result['inquiry_type'] = $order_inquiry['inquiry_type']; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药) + $result['pay_config'] = $pay_config; // 小程序支付配置 return success($result); } diff --git a/app/Utils/Auth.php b/app/Utils/Auth.php index 01aa3ba..5599234 100644 --- a/app/Utils/Auth.php +++ b/app/Utils/Auth.php @@ -23,6 +23,7 @@ class Auth "/area/province" => "get",// 获取省份信息 "/area/city" => "get", // 获取城市信息 "/area/county" => "get", // 获取区县信息 + "/pay/wx/callback" => "post", // 微信支付回调 ]; } diff --git a/config/routes.php b/config/routes.php index 825c61e..82a7797 100644 --- a/config/routes.php +++ b/config/routes.php @@ -22,6 +22,7 @@ use App\Controller\PatientCaseController; use App\Controller\PatientCenterController; use App\Controller\PatientDoctorController; use App\Controller\PatientFamilyController; +use App\Controller\PayController; use App\Controller\SafeController; use App\Controller\SystemController; use App\Controller\UserController; @@ -194,6 +195,9 @@ Router::addGroup('/patient', function () { Router::addGroup('/order', function () { // 创建订单 Router::post('', [InquiryController::class, 'addInquiryOrder']); + + // 创建订单 + Router::post('/test', [InquiryController::class, 'addInquiryOrderTest']); }); // 检测是否可以接诊 @@ -320,3 +324,11 @@ Router::addGroup('/system', function () { Router::get('/config', [SystemController::class, 'getSystemInquiryConfig']); }); }); + +// 支付回调 +Router::addGroup('/pay', function () { + // 支付回调 + Router::addGroup('/wx', function () { + Router::post('/callback', [PayController::class, 'wxCallBack']); + }); +}); diff --git a/extend/Wechat/WechatPay.php b/extend/Wechat/WechatPay.php index e7813cb..299f5b8 100644 --- a/extend/Wechat/WechatPay.php +++ b/extend/Wechat/WechatPay.php @@ -2,15 +2,45 @@ namespace Extend\Wechat; +use App\Constants\HttpEnumCode; +use App\Exception\BusinessException; +use EasyWeChat\Kernel\Exceptions\InvalidArgumentException; +use EasyWeChat\Kernel\Exceptions\InvalidConfigException; +use EasyWeChat\Pay\Application; +use Hyperf\Utils\ApplicationContext; +use Psr\SimpleCache\CacheInterface; + /** * 微信支付类 */ class WechatPay { - protected $app; + protected array $config;// 系统配置 - // 创建工厂类 - public function createApp(){ + /** + * @param string $user_type + */ + public function __construct(string $user_type) + { + if ($user_type == 1){ + $this->config = config("we_chat.applets.patient"); + }elseif ($user_type == 2){ + $this->config = config("we_chat.applets.doctor"); + }elseif ($user_type == 3){ + $this->config = config("we_chat.applets.pharmacist"); + } + + if (empty($this->config)){ + throw new BusinessException("系统配置错误", HttpEnumCode::SERVER_ERROR); + } + } + + /** + * 创建工厂类 + * @return Application + */ + public function createApp(): Application + { $config = [ 'mch_id' => config("we_chat.pay.mch_id"), @@ -28,7 +58,7 @@ class WechatPay // 下载工具:https://github.com/wechatpay-apiv3/CertificateDownloader 'platform_certs' => [ // 请使用绝对路径 - __DIR__ . '/certs/wechatpay_112FCCD1B9ECC8292703AB7363C73D74B6AFDC1A.pem', + __DIR__ . '/certs/' . config("we_chat.pay.mch_id") . '/wechatpay_112FCCD1B9ECC8292703AB7363C73D74B6AFDC1A.pem', ], /** @@ -41,5 +71,84 @@ class WechatPay // 'base_uri' => 'https://api.mch.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri ], ]; + + try { + return new Application($config); + } catch (InvalidArgumentException $e) { + throw new BusinessException('实例化EasyWeChat类失败:' . $e->getMessage(), HttpEnumCode::SERVER_ERROR); + } + } + + /** + * 获取jsapi预支付交易会话标识 + * @param string $out_trade_no 商户系统内部订单号 + * @param int $total 支付金额(实际金额x100) + * @param string $openid + * @return array + */ + public function getJsapiPrepayId(string $out_trade_no,int $total,string $openid): array + { + $app = $this->createApp(); + + $options = [ + "mchid" => config("we_chat.pay.mch_id"), // <---- 商户号 + "out_trade_no" => $out_trade_no, // 商户系统内部订单号 + "appid" => $this->config['app_id'], + "description" => "问诊服务", + "notify_url" => "https://dev.hospital.applets.igandanyiyuan.com/pay/wx/callback", + "amount" => [ + "total" => $total,//订单总金额,单位为分。 + "currency" => "CNY" + ], + "payer" => [ + "openid" => $openid // 下单用户的 openid + ] + ]; + + try { + $response = $app->getClient()->postJson("v3/pay/transactions/jsapi", $options); + dump($response->toArray(false)); + if ($response->isFailed()) { + // 出错了,处理异常 + $result = $response->toArray(false); + if(empty($result)){ + // 返回值为空 + throw new BusinessException("发起支付失败"); + } + if (!empty($result['code'])){ + throw new BusinessException($result['message']); + } + throw new BusinessException("发起支付失败"); + } + + return $response->toArray(false); + } catch (\Exception $e) { + throw new BusinessException($e->getMessage(), HttpEnumCode::SERVER_ERROR); + } + } + + /** + * 获取小程序支付配置 + * @param string $prepay_id 预支付交易会话标识 + * @return array + */ + public function getAppletsPayConfig(string $prepay_id): array + { + + try { + $app = $this->createApp(); + $utils = $app->getUtils(); + + $appId = $this->config['app_id']; + $signType = 'RSA'; // 默认RSA,v2要传MD5 + + $config = $utils->buildMiniAppConfig($prepay_id, $appId, $signType); + if (empty($config)){ + throw new BusinessException("发起支付失败"); + } + return $config; + } catch (\Exception $e) { + throw new BusinessException($e->getMessage(), HttpEnumCode::SERVER_ERROR); + } } } \ No newline at end of file