
支付宝
注册
首先要注册两个平台账号,一个是支付宝商户平台,一个是支付宝开放平台,需要企业账号实名认证,免费。
没有条件的可以是用支付宝模拟沙箱进行测试。
开发前置
- 支付宝开放平台注册后,申请一个应用,获得APPID,例如我要开发一个网站的支付,我就申请一个 网页/移动应用 的应用。
- 支付宝商户平台注册后,获得商户ID,然后将前面的APPID与商户ID绑定。
- 支付宝开放平台设置获取
- 密钥(即:应用私钥、应用公钥、支付宝公钥) ,有两种,一种是公钥模式,一种是证书模式,公钥模式可不上传证书。
- 应用网关(用来接收支付宝异步通知信息)
- 回调地址(支付后的回调,可以设置只验证域名)。
下载SDK
前往官网下载SDK,支付宝SDK有两种,一种是通用版,一种是easy版,简单来说通用版适用于非框架,easy版适用于框架。
- 通用版:
- 这里以Laravel为例,放入/app/alipay目录下(可以随自己喜欢换别的位置),然后composer.json里的autoload下classmap里加入一行”app/alipay”来载入SDK:
| "classmap": [ |
| "app/alipay" |
| ] |
之后在CMD里运行composer dump-autoload命令,就可以使用SDK了
composer dump-autoload
- easy版:
- 运行composer命令
composer require alipaysdk/easysdk:^2.0
配置信息
- 在config目录里新建一个alipay.php,在里面配置信息(在前面的支付宝开放平台都可以获取)
| <?php |
| return [ |
| |
| 'app_id' => "", |
| |
| |
| 'merchant_private_key' => "", |
| |
| |
| 'notify_url' => "http://工程公网访问地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php", |
| |
| |
| 'return_url' => "http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php", |
| |
| |
| 'charset' => "UTF-8", |
| |
| |
| 'sign_type'=>"RSA2", |
| |
| |
| 'screct_key' => '', |
| |
| |
| 'gatewayUrl' => "https://openapi.alipay.com/gateway.do", |
| |
| |
| 'alipay_public_key' => "", |
| |
| |
| 'log_path' => "", |
| ]; |
ps:沙箱环境和正式环境网关不一样的
| |
| 'gatewayUrl' => "https://openapi.alipay.com/gateway.do", |
| |
| 'gatewayUrl' => "https://openapi.alipaydev.com/gateway.do", |
支付宝支付代码
这里以网站支付为例,可参考SDK文档
- 通用版
| $config = config("alipay"); |
| |
| $out_trade_no = time() . mt_rand(1111, 9999); |
| |
| $subject = trim("Q币订单支付"); |
| |
| |
| $total_amount = 499; |
| |
| |
| $body = "EDG皮肤大礼包"; |
| |
| |
| $payRequestBuilder = new AlipayTradePagePayContentBuilder(); |
| $payRequestBuilder->setBody($body); |
| $payRequestBuilder->setSubject($subject); |
| $payRequestBuilder->setTotalAmount($total_amount); |
| $payRequestBuilder->setOutTradeNo($out_trade_no); |
| |
| $aop = new AlipayTradeService($config); |
| |
| |
| |
| |
| |
| |
| |
| |
| return $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']); |
- easy版
| |
| $config = config('alipay'); |
| $options = new Config(); |
| $options->protocol = 'https'; |
| $options->gatewayHost = 'openapi.alipay.com'; |
| $options->signType = 'RSA2'; |
| |
| $options->appId = $config['app_id']; |
| |
| |
| $options->merchantPrivateKey = $config['merchant_private_key']; |
| $options->gatewayHost = "openapi.alipaydev.com"; |
| |
| $options->alipayPublicKey = $config['alipay_public_key']; |
| |
| $options->notifyUrl = $config['notify_url']; |
| |
| |
| |
| Factory::setOptions($options); |
| try { |
| |
| $result = Factory::payment()->page()->pay("iPhone6 16G", "2020423435526001", "88.88", $config['return_url']); |
| return $result->body; |
| } catch (Exception $e) { |
| echo "调用失败,". $e->getMessage(). PHP_EOL;; |
| } |
- 其他调用方法可以在alipaysdk里找到API文档进行调用,例如手机网站H5支付:
| $result = Factory::payment()->wap()->pay("Q币充值标题", "订单号", 88.88, "支付失败跳转URL", "支付成功同步跳转URL"); |
| return $result->body; |
支付
- 支付成功后会跳转到之前配置的同步GET跳转URL,然后支付宝会发送一个POST请求到异步通知URL。
| $params = $request->all(); |
| echo '购买成功!'; |
支付回调
- 非必需,防止数据泄露被恶意调用接口。支付宝验签要将所有参数拼接成字符串验签,所以不要带入多余的参数。
- 通用版
| $params = $request->all(); |
| $config = config("alipay"); |
| $aop = new AlipayTradeService($config); |
| $config = config("alipay"); |
| |
| if($aop->check($params)) |
| { |
| echo '验签成功'; |
| } |
- easy版
| $config = config('alipay'); |
| $params = $request->all(); |
| $Signer = new Signer(); |
| |
| $v = $Signer->verifyParams($params, $config['alipay_public_key']); |
| if($v) |
| { |
| echo '验签成功'; |
| } |
微信
注册
- 注册和微信商户平台。微信商户需要微信认证(支付300块钱)。
- 注册完成后获取信息
下载SDK
这里我们直接使用easywechat工具来进行开发,由于我们使用的是Laravel,可以下载easywechat的laravel版本
composer require "overtrue/laravel-wechat:~5.0"
配置文件
运行命令
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
会在config目录生成wechat.php
修改wechat.php
| /* |
| * 微信支付 |
| */ |
| 'payment' => [ |
| 'default' => [ |
| 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false), |
| 'app_id' => env('WECHAT_PAYMENT_APPID', '你的appid'), |
| 'mch_id' => env('WECHAT_PAYMENT_MCH_ID', '你的商户ID'), |
| 'key' => env('WECHAT_PAYMENT_KEY', '你的key'), |
| 'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', '/cert/apiclient_cert.pem'), // XXX: 绝对路径!!!! |
| 'key_path' => env('WECHAT_PAYMENT_KEY_PATH', '/cert/apiclient_key.pem'), // XXX: 绝对路径!!!! |
| 'notify_url' => 'http://www.baidu.com', // 默认支付结果通知地址 |
| ], |
| // ... |
| ], |
支付代码
类型
注意金额字段total_fee的数是要*100的,比如1块钱应该写100,trade_type类型是支付方式,其他方式为:
JSAPI–JSAPI支付(或小程序支付)、NATIVE–Native支付、APP–app支付,MWEB–H5支付,不同trade_type决定了调起支付的方式,请根据支付产品正确上传
扫码支付
| $config = config('wechat.payment.default'); |
| $app = Factory::payment($config); |
| $result = $app->order->unify([ |
| 'body' => 'Q币微信支付', |
| 'out_trade_no' => 随机生成的订单号, |
| 'total_fee' => 1 * 100, |
| 'trade_type' => 'NATIVE', // 请对应换成你的支付方式对应的值类型 |
| ]); |
| $result['total'] = $data['total']; |
| |
| return $result; |
这里我使用的是Native支付,会返回一个二维码,SDK 并不内置二维码生成库,使用你熟悉的工具创建二维码即可,比如 PHP 部分有以下工具可以选择
H5支付
| $config = config('wechat.payment.default'); |
| $app = Factory::payment($config); |
| $result = $app->order->unify([ |
| 'body' => 'Q币微信支付', |
| 'out_trade_no' => 随机生成的订单号, |
| 'total_fee' => 1 * 100, |
| 'trade_type' => 'MWEB', // 请对应换成你的支付方式对应的值类型 |
| ]); |
| $result['total'] = $data['total']; |
| |
| return redirect($result['mweb_url']); |
这个是在非微信浏览器下进行的H5支付,如果要进行微信内部浏览器H5支付,需要使用JSSDK支付。
JSSDK支付
- 先申请公众号,然后配置公众号信息
| /* |
| * 公众号 |
| */ |
| 'official_account' => [ |
| 'default' => [ |
| 'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', '你的AppID'), // AppID |
| 'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', '你的secret'), // AppSecret |
| 'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', '你的token'), // Token |
| 'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', '你的aes加密key') |
| ] |
| ] |
- 用接口获取openid。这里使用easywechat封装好的user()方法获取openid,先通过authorize接口获取code,然后通过code获取openid,之后可以考虑将openid存在session里,或者数据库等其他地方。
| if ($request->has('code')) |
| { |
| $config = config('wechat.official_account.default'); |
| $c = \EasyWeChat\Factory::officialAccount($config); |
| $rs = $c->oauth->user(); |
| return redirect("你的订单页面?openid=" . $rs['original']['openid']); |
| } |
| |
| $currentUrl = urlencode(url()->current()); |
| $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe96b27ac2a780cb1&redirect_uri={$currentUrl}&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect"; |
| return redirect($url); |
- 用前面获取的openid去下单,然后这里有三种js支付方式:WeixinJSBridge, JSSDK, 小程序
| $config = config('wechat.payment.default'); |
| $app = \EasyWeChat\Factory::payment($config); |
| |
| $result = $app->order->unify([ |
| 'body' => 'Q币订单微信支付', |
| 'out_trade_no' => 随机生成的订单号, |
| 'total_fee' => 1 * 100, |
| 'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 |
| 'openid' => $openid, |
| ]); |
| // 未完待续 |
- WeixinJSBridge
- PHP
$json = $jssdk->bridgeConfig($prepayId); // 返回 json 字符串,如果想返回数组,传第二个参数 false
- JavaScript
| WeixinJSBridge.invoke( |
| 'getBrandWCPayRequest', $json, |
| function(res){ |
| if(res.err_msg == "get_brand_wcpay_request:ok" ) { |
| |
| |
| |
| } |
| } |
| ); |
- JSSDK
- PHP
$config = $jssdk->sdkConfig($prepayId); // 返回数组
- JavaScript
| wx.chooseWXPay({ |
| timestamp: <?= $config['timestamp'] ?>, |
| nonceStr: '<?= $config['nonceStr'] ?>', |
| package: '<?= $config['package'] ?>', |
| signType: '<?= $config['signType'] ?>', |
| paySign: '<?= $config['paySign'] ?>', // 支付签名 |
| success: function (res) { |
| // 支付成功后的回调函数 |
| } |
| }); |
- 小程序
- PHP
$config = $jssdk->bridgeConfig($prepayId, false);
- JavaScript
| wx.requestPayment({ |
| timeStamp: <?= $config['timeStamp'] ?>, //注意 timeStamp 的格式 |
| nonceStr: '<?= $config['nonceStr'] ?>', |
| package: '<?= $config['package'] ?>', |
| signType: '<?= $config['signType'] ?>', |
| paySign: '<?= $config['paySign'] ?>', // 支付签名 |
| success: function (res) { |
| // 支付成功后的回调函数 |
| } |
| }); |
支付回调
微信支付成功后会有一个支付回调,这里返回的是XML,需要解析才能使用
| $xml = $request->getContent(); |
| $param = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); |
| echo 'Q币充值成功'; |