赞
踩
composer require overtrue/wechat:~4.0 -vvv
修改 SWOOLE_HOOK_FLAGS
编辑 bin/hyperf.php
文件
- <?php
-
- ! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL);
创建配置文件 config/autoload/wechat.php
touch config/autoload/wechat.php
- <?php
- declare(strict_types=1);
-
- return [
- /*
- * 小程序
- */
- 'mini_program' => [
- 'default' => [
- 'app_id' => env('WECHAT_MINI_PROGRAM_APPID', ''),
- 'secret' => env('WECHAT_MINI_PROGRAM_SECRET', ''),
- 'token' => env('WECHAT_MINI_PROGRAM_TOKEN', ''),
- 'aes_key' => env('WECHAT_MINI_PROGRAM_AES_KEY', ''),
- ],
- ],
-
- /*
- * 微信支付
- */
- 'payment' => [
- 'default' => [
- 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false),
- 'app_id' => env('WECHAT_PAYMENT_APPID', ''),
- 'mch_id' => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
- 'key' => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
- 'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'), // XXX: 绝对路径!!!!
- 'key_path' => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'), // XXX: 绝对路径!!!!
- 'notify_url' => env('WECHAT_PAYMENT_NOTIFY_URL', ''), // 默认支付结果通知地址
- ],
- // ...
- ],
- ];
编辑 .env 文件
- # EasyWechat 小程序账号
- WECHAT_MINI_PROGRAM_APPID=wx46f4f2***
- WECHAT_MINI_PROGRAM_SECRET=28ddcd98d139a53*****
- WECHAT_MINI_PROGRAM_TOKEN=
- WECHAT_MINI_PROGRAM_AES_KEY=
-
- # 支付
- WECHAT_PAYMENT_SANDBOX=false
- WECHAT_PAYMENT_APPID=wx46f4f2***
- WECHAT_PAYMENT_MCH_ID=1517****
- WECHAT_PAYMENT_KEY=Mm4vhqTUQaskidBr*****
- WECHAT_PAYMENT_CERT_PATH=
- WECHAT_PAYMENT_KEY_PATH=
- WECHAT_PAYMENT_NOTIFY_URL=http://yourdomain/payments/notify
- mkdir -p app/Kernel/Oauth
- touch app/Kernel/Oauth/WeChatFactory.php
文件内容如下:
- <?php
-
- declare(strict_types=1);
-
- namespace App\Kernel\Oauth;
-
- use EasyWeChat\Factory;
- use GuzzleHttp\Client;
- use GuzzleHttp\HandlerStack;
- use Hyperf\Contract\ConfigInterface;
- use Hyperf\Guzzle\CoroutineHandler;
- use Hyperf\Guzzle\HandlerStackFactory;
- use Overtrue\Socialite\Providers\AbstractProvider;
- use Psr\Container\ContainerInterface;
- use Hyperf\Utils\ApplicationContext;
- use Psr\SimpleCache\CacheInterface;
-
- class WeChatFactory
- {
- /**
- * @var ContainerInterface
- */
- protected $container;
-
- private $config;
-
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- $this->config = $container->get(ConfigInterface::class)->get('wechat.mini_program.default');
-
- // 设置 OAuth 授权的 Guzzle 配置
- AbstractProvider::setGuzzleOptions([
- 'http_errors' => false,
- 'handler' => HandlerStack::create(new CoroutineHandler()),
- ]);
- }
-
- /**
- * @return \EasyWeChat\MiniProgram\Application
- */
- public function create()
- {
- $app = Factory::miniProgram($this->config);
-
- // 设置 HttpClient,当前设置没有实际效果,在数据请求时会被 guzzle_handler 覆盖,但不保证 EasyWeChat 后面会修改这里。
- $config = $app['config']->get('http', []);
- $config['handler'] = $this->container->get(HandlerStackFactory::class)->create();
- $app->rebind('http_client', new Client($config));
-
- // 重写 Handler
- $app['guzzle_handler'] = $this->container->get(HandlerStackFactory::class)->create();
- // 重新 Cache
- $app['cache'] = ApplicationContext::getContainer()->get(CacheInterface::class);
- return $app;
- }
-
- }
新建登录控制器
php bin/hyperf.php gen:controller AuthController
大致内容如下:
- <?php
-
- declare(strict_types=1);
-
- namespace App\Controller;
-
- use App\Kernel\Oauth\WeChatFactory;
-
- use Hyperf\Di\Annotation\Inject;
- use Hyperf\HttpServer\Annotation\AutoController;
- use Hyperf\HttpServer\Contract\RequestInterface;
- use Hyperf\HttpServer\Contract\ResponseInterface;
-
- /**
- * @AutoController()
- * Class AuthController
- * @package App\Controller
- */
- class AuthController
- {
- /**
- * @Inject()
- * @var WeChatFactory
- */
- protected $factory;
-
- public function login(RequestInterface $request,ResponseInterface $response)
- {
- $code = $request->input('code');
- $encryptedData = $request->input('encrypted_data');
- $iv = $request->input('iv');
-
- $app = $this->factory->create();
- $session = $app->auth->session($code);
- $userInfo = $app->encryptor->decryptData($session['session_key'], $iv, $encryptedData);
- var_dump($userInfo);
- return $userInfo;
- }
- }
前端 uni-app 登录
- <template>
- <view>
- <button open-type="getUserInfo" @getuserinfo="login" withCredentials="true">注册</button>
- </view>
- </template>
- <script>
- export default {
- data() {},
- onLoad() {},
- methods: {
- async login(res) {
- var encryptedData = res.detail.encryptedData
- var iv = res.detail.iv;
-
- var [, res] = await uni.login({
- provider: 'weixin'
- });
-
- var code = res.code;
-
- uni.request({
- url: 'http://127.0.0.1:9501/auth/login',
- method: 'POST',
- data: {
- code: code,
- encrypted_data: encryptedData,
- iv: iv
- },
- success: (res) => {
- console.log(res.data);
- }
- });
- },
- },
- }
- </script>
新建一个 app\Kernel\Payment\WeChatFactory.php
文件
- mkdir -p app/Kernel/Payment
- touch app/Kernel/Payment/WeChatFactory.php
- <?php
-
- declare(strict_types=1);
-
- namespace App\Kernel\Payment;
-
- use EasyWeChat\Factory;
- use GuzzleHttp\Client;
- use GuzzleHttp\HandlerStack;
- use Hyperf\Contract\ConfigInterface;
- use Hyperf\Guzzle\CoroutineHandler;
- use Hyperf\Guzzle\HandlerStackFactory;
- use Overtrue\Socialite\Providers\AbstractProvider;
- use Psr\Container\ContainerInterface;
- use Hyperf\Utils\ApplicationContext;
- use Psr\SimpleCache\CacheInterface;
-
- class WeChatFactory
- {
- /**
- * @var ContainerInterface
- */
- protected $container;
-
- protected $paymentConfig;
-
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- $this->paymentConfig = $container->get(ConfigInterface::class)->get('wechat.payment.default');
-
- // 设置 OAuth 授权的 Guzzle 配置
- AbstractProvider::setGuzzleOptions([
- 'http_errors' => false,
- 'handler' => HandlerStack::create(new CoroutineHandler()),
- ]);
- }
-
- /**
- * @return \EasyWeChat\Payment\Application
- */
- public function payment()
- {
- $app = Factory::payment($this->paymentConfig);
-
- // 设置 HttpClient,当前设置没有实际效果,在数据请求时会被 guzzle_handler 覆盖,但不保证 EasyWeChat 后面会修改这里。
- $config = $app['config']->get('http', []);
- $config['handler'] = $this->container->get(HandlerStackFactory::class)->create();
- $app->rebind('http_client', new Client($config));
-
- // 重写 Handler
- $app['guzzle_handler'] = $this->container->get(HandlerStackFactory::class)->create();
- // 重新 Cache
- $app['cache'] = ApplicationContext::getContainer()->get(CacheInterface::class);
- return $app;
- }
- }
新建支付控制器
php bin/hyperf.php gen:controller PaymentsController
代码如下:
- <?php
-
- declare(strict_types=1);
-
- namespace App\Controller;
-
- use App\Kernel\Payment\WeChatFactory;
- use EasyWeChat\Kernel\Exceptions\Exception;
- use Hyperf\Di\Annotation\Inject;
- use Hyperf\HttpServer\Annotation\AutoController;
- use Hyperf\HttpServer\Annotation\Middleware;
- use Hyperf\HttpServer\Contract\RequestInterface;
- use Hyperf\HttpServer\Contract\ResponseInterface;
- use Hyperf\Logger\LoggerFactory;
- use Symfony\Component\HttpFoundation\Request;
- use function EasyWeChat\Kernel\Support\generate_sign;
-
- /**
- * @AutoController()
- * Class PaymentsController
- * @package App\Controller
- */
- class PaymentsController extends AbstractController
- {
-
- /**
- * @Inject()
- * @var WeChatFactory
- */
- protected $factory;
-
- /**
- * @var \Psr\Log\LoggerInterface
- */
- protected $logger;
-
- protected $rechargeDao;
-
- public function __construct(LoggerFactory $loggerFactory)
- {
- // 第一个参数对应日志的 name, 第二个参数对应 config/autoload/logger.php 内的 key
- $this->logger = $loggerFactory->get('log', 'default');
- }
-
- public function index(RequestInterface $request, ResponseInterface $response)
- {
- $this->logger->info("支付开始");
-
- $app = $this->factory->payment();
-
- $result = $app->order->unify([
- 'body' => 'QQ 会员充值',
- 'out_trade_no' => time(),
- 'total_fee' => 10,
- //'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
- 'notify_url' => config('wechat.payment.default.notify_url'), // 支付结果通知网址,如果不设置则会使用配置里的默认地址
- 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
- 'openid' => 'ogPdd5bAEOp3tZL1nxavbx7'
- ]);
-
- if ($result['return_code'] === 'SUCCESS' && $result['return_msg'] === 'OK')
- {
- // 二次验签
- $params = [
- 'appId' => config('wechat.payment.default.app_id'),
- 'timeStamp' => time(),
- 'nonceStr' => $result['nonce_str'],
- 'package' => 'prepay_id=' . $result['prepay_id'],
- 'signType' => 'MD5',
- ];
-
- // config('wechat.payment.default.key')为商户的key
- $params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
- return $params;
- }
- else{
- //
- }
- }
-
- public function notify(RequestInterface $request, ResponseInterface $response)
- {
- $this->logger->info("收到回调");
-
- $app = $this->factory->payment();
- $get = $this->request->getQueryParams();
- $post = $this->request->getParsedBody();
- $cookie = $this->request->getCookieParams();
- $files = $this->request->getUploadedFiles();
- $server = $this->request->getServerParams();
- $xml = $this->request->getBody()->getContents();
-
- $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
-
- $app->handlePaidNotify(function ($message, $fail) {
- $this->logger->error($message['out_trade_no']);
- $this->logger->info($message['return_code']);
- $this->logger->info('回调数据'.json_encode($message));
-
- if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
- // 用户是否支付成功
-
- }
- // 用户支付失败
- return false;
- });
- }
- }
小程序掉起支付代码
- <template>
- <view>
- <button @tap="payment">服务订单支付</button>
- </view>
- </template>
- <script>
- export default {
- data() {},
- onLoad() {},
- methods: {
- async payment() {
- const token = uni.getStorageSync('token');
- uni.getProvider({
- service: 'payment',
- success: function(res) {
- var provider = res.provider[0];
- uni.request({
- url: 'http:127.0.0.1:9501/payments/index',
- method: 'POST',
- data: {},
- success: (res) => {
- uni.requestPayment({
- provider: provider,
- orderInfo: '腾讯充值中心-QQ会员充值',
- timeStamp: res.data.timeStamp.toString(),
- nonceStr: res.data.nonceStr,
- package: res.data.package,
- signType: res.data.signType,
- paySign: res.data.paySign,
- _deguh: 1,
- success(res) {
- console.log(res);
- },
- fail(res) {
- console.log(res);
- }
- })
- }
- });
- }
- })
- },
- },
- }
- </script>
至于微信回调地址就得需要生产环境来测试了,沙箱环境我没有测试过,也懒的搞。这里截张生产环境下的回调 Log 信息
极客返利 是由我个人开发的一款网课返利、返现平台。包含 极客时间返现、拉勾教育返现、掘金小册返现、GitChat返现。目前仅包含这几个平台。后续如果有需要可以考虑其他平台。 简而言之就是:你买课,我返现。让你花更少的钱,就可以买到课程。
本作品采用 知识共享署名 4.0 国际许可协议 进行许可。转载无需与我联系,但须注明出处,注明文章来源 Hyperf + uni-app 使用 EasyWechat 实现微信小程序登录和支付
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。