安装EasySwoole支付SDK
composer require easyswoole/pay
配置信息
需要在公众号和商户号授权当前项目域名
添加微信支付配置信息,并将证书上传至根目录
/**################ 微信支付配置 CONFIG ##################*/
'WX' => [
'AppId' => '微信公众号APPID',
'Secret' => '微信公众号Secret',
'MchId' => '商户号ID',
'Key' => '商户支付秘钥',
'ApiClientCert' => EASYSWOOLE_ROOT.'/apiclient_cert.pem',
'ApiClientKey' => EASYSWOOLE_ROOT.'/apiclient_key.pem',
],
代码实现
支付流程:通过网页授权获取用户OPENID->请求微信统一下单接口->微信内H5网页发起支付请求
创建http控制器\App\HttpController\Pay.php
<?php
namespace App\HttpController;
use EasySwoole\EasySwoole\Config;
use EasySwoole\Http\AbstractInterface\Controller;
class Pay extends Controller
{
protected $param; //请求参数
protected $wechatConfig ; //微信配置信息
protected function onRequest(?string $action): ?bool
{
$this->param = $this->request()->getRequestParam(); //接收请求参数
$this->wechatConfig = Config::getInstance()->getConf('WX');
return true;
}
/**
* JSAPI支付
*/
public function index()
{
$params = $this->request()->getRequestParam();
if(!isset($params['code'])){
$this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
$scope = "snsapi_base";
$state = md5(time());
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->wechatConfig['AppId']."&redirect_uri=http://www.go1s.cn/pay/index?response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
$this->response()->redirect($url);
return false;
}else {
//用code获取access_token
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->wechatConfig['AppId']."&secret=".$this->wechatConfig['Secret']."&code=".$this->param["code"]."&grant_type=authorization_code";
//获取 access_token openid scope
$res = \EasySwoole\Pay\Utility\NewWork::get($url,[])->getBody(); //$this->https_request($url);
$res = json_decode($res,true);
$openid = $res["openid"]; //当前用户的openid
$access_token = $res["access_token"]; //access_token 获取共享收货地址参数需要次参数
$wechatConfig = new \EasySwoole\Pay\WeChat\Config();
$wechatConfig->setAppId($this->wechatConfig['AppId']); // 公众号APPID
$wechatConfig->setMchId($this->wechatConfig['MchId']); //商户号
$wechatConfig->setKey($this->wechatConfig['Key']);//支付key
$wechatConfig->setNotifyUrl('http://www.go1s.cn/pay/notify'); //支付回调地址
$wechatConfig->setApiClientCert($this->wechatConfig['ApiClientCert']);//客户端证书
$wechatConfig->setApiClientKey($this->wechatConfig['ApiClientKey']); //客户端证书秘钥
$officialAccount = new \EasySwoole\Pay\WeChat\RequestBean\OfficialAccount();
$officialAccount->setOpenid($openid);
$outTradeNo = 'CN' . date('YmdHis') . rand(1000, 9999);
echo "MP--- " . $outTradeNo . "\r\n";
$officialAccount->setOutTradeNo($outTradeNo);
$officialAccount->setBody('xxxxx-测试' . $outTradeNo);
$officialAccount->setTotalFee(1);
$officialAccount->setSpbillCreateIp($this->getClientIp());
$pay = new \EasySwoole\Pay\Pay();
$params = $pay->weChat($wechatConfig)->officialAccount($officialAccount);
$jsApiParameters = $params->toArray();
$str = <<<EOF
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>微信JSAPI支付-订单支付</title>
<script type="text/javascript" charset="UTF-8" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{'appId':'{$jsApiParameters['appId']}',
'nonceStr':'{$jsApiParameters['nonceStr']}',
'package':'{$jsApiParameters['package']}',
'signType':'{$jsApiParameters['signType']}',
'timeStamp':'{$jsApiParameters['timeStamp']}',
'paySign':'{$jsApiParameters['paySign']}'},
function (res) {
WeixinJSBridge.log(res.err_msg);
//alert(res.err_code+res.err_desc+res.err_msg);
if(res.err_msg=='get_brand_wcpay_request:cancel'){
alert("您已取消支付,即将跳转取消支付页面");
window.location.href="/Pay/payCancel";
return false;
}
if(res.err_msg=='get_brand_wcpay_request:fail'){
alert("支付失败,即将跳转错误页面");
window.location.href="/Pay/payError";
return false;
}
if(res.err_msg=='get_brand_wcpay_request:ok'){
alert("支付成功,即将跳转成功页面");
//完成之后的一些逻辑
window.location.href="/Pay/paySuccess";
}
}
);
}
function callpay() {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
} else {
jsApiCall();
}
}
</script>
</head>
<body>
<br/>
<div align="center">
<font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/>
<button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()">立即支付
</button>
</div>
</body>
</html>
EOF;
$this->response()->write($str);
}
}
/**
* JSAPI支付异步回调
*/
public function notify(){
$content = $this->request()->getBody()->__toString();
$pay = new \EasySwoole\Pay\Pay();
$wechatConfig = new \EasySwoole\Pay\WeChat\Config();
$wechatConfig->setAppId($this->wechatConfig['AppId']); // 公众号APPID
$wechatConfig->setMchId($this->wechatConfig['MchId']); //商户号
$wechatConfig->setKey($this->wechatConfig['Key']);//支付key
$wechatConfig->setNotifyUrl('http://www.go1s.cn/pay/notify'); //支付回调地址
$wechatConfig->setApiClientCert($this->wechatConfig['ApiClientCert']);//客户端证书
$wechatConfig->setApiClientKey($this->wechatConfig['ApiClientKey']); //客户端证书秘钥
$data = $pay->weChat($wechatConfig)->verify($content);
$msg = "[" . date('Y-m-d H:i:s') . "]" . $data->__toString() . "\r\n";
file_put_contents(EASYSWOOLE_ROOT. '/Temp/notify-' . date('Y-m-d') . '.log', $msg, FILE_APPEND);
$this->response()->write(\EasySwoole\Pay\WeChat\WeChat::success());
}
/**
* http携程客户端请求微信API
*/
public function https_request($url, $data = [])
{
//实例化 http携程客户端
$client = new \EasySwoole\HttpClient\HttpClient($url);
$response = $client->get();
return $response->getBody();
}
/**
* 获取当前客户端IP
*/
protected function getClientIp(){
if (count($this->request()->getHeader('x-real-ip'))) {
$ip = $this->request()->getHeader('x-real-ip')[0];
} else {
$params = $this->request()->getServerParams();
foreach (['http_client_ip', 'http_x_forward_for', 'x_real_ip', 'remote_addr'] as $key) {
if (isset($params[$key]) && !strcasecmp($params[$key], 'unknown')) {
$ip = $params[$key];
break;
}
}
}
return $ip;
}
/**
* 支付成功
*/
public function paySuccess(){
$this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
$this->response()->write('<h1>支付成功</h1>');
}
/**
* 支付错误
*/
public function payError(){
$this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
$this->response()->write('<h1>支付异常</h1>');
}
/**
* 取消支付
*/
public function payCancel(){
$this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
$this->response()->write('<h1>取消支付</h1>');
}
/**
* 异常抛出
**/
public function onException(\Throwable $throwable): void
{
$path = $this->request()->getUri()->getPath();
$this->writeJson(\EasySwoole\Http\Message\Status::CODE_INTERNAL_SERVER_ERROR, $throwable->getMessage(), "服务器异常");
}
}
查看结果
微信访问支付链接 http://域名:端口/pay/index
本文为够意思原创文章,转载无需和我联系,但请注明来自够意思博客blog.go1s.cn:够意思博客 » EasySwoole 实现微信JSAPI支付