PHP-Laravel支付宝支付和微信支付

支付宝

注册

首先要注册两个平台账号,一个是支付宝商户平台,一个是支付宝开放平台,需要企业账号实名认证,免费。
没有条件的可以是用支付宝模拟沙箱进行测试。

开发前置
  1. 支付宝开放平台注册后,申请一个应用,获得APPID,例如我要开发一个网站的支付,我就申请一个 网页/移动应用 的应用。
  2. 支付宝商户平台注册后,获得商户ID,然后将前面的APPID与商户ID绑定。
  3. 支付宝开放平台设置获取
    • 密钥(即:应用私钥、应用公钥、支付宝公钥) ,有两种,一种是公钥模式,一种是证书模式,公钥模式可不上传证书。
      • 应用网关(用来接收支付宝异步通知信息)
      • 回调地址(支付后的回调,可以设置只验证域名)。
下载SDK

前往官网下载SDK,支付宝SDK有两种,一种是通用版,一种是easy版,简单来说通用版适用于非框架,easy版适用于框架。

  1. 通用版:
    这里以Laravel为例,放入/app/alipay目录下(可以随自己喜欢换别的位置),然后composer.json里的autoload下classmap里加入一行”app/alipay”来载入SDK:
"classmap": [
      "app/alipay"
]

之后在CMD里运行composer dump-autoload命令,就可以使用SDK了

composer dump-autoload
  1. easy版:
    运行composer命令
    composer require alipaysdk/easysdk:^2.0
    配置信息
    在config目录里新建一个alipay.php,在里面配置信息(在前面的支付宝开放平台都可以获取)
<?php
return [    
        //应用ID,您的APPID。
        'app_id' => "",

        //商户私钥,您的原始格式RSA私钥
        '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",

        //接口加密key(没有设置可不用)
        'screct_key' => '',

        //支付宝网关
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        'alipay_public_key' => "",

        //日志路径
        'log_path' => "",
];

ps:沙箱环境和正式环境网关不一样的

//支付宝正式环境网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付宝沙箱环境网关
'gatewayUrl' => "https://openapi.alipaydev.com/gateway.do",
支付宝支付代码

这里以网站支付为例,可参考SDK文档

  1. 通用版

     $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);
    
     /**
     * pagePay 电脑网站支付请求
     * @param $builder 业务参数,使用buildmodel中的对象生成。
     * @param $return_url 同步跳转地址,公网可以访问
     * @param $notify_url 异步通知地址,公网可以访问
     * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) $response 支付宝返回的信息
     */
     return $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
  2. easy版

    //1. 设置参数(全局只需设置一次)
             $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'];
    
             //可设置AES密钥,调用AES加解密相关接口时需要(可选)
             // $options->encryptKey = $config['screct_key'];
             Factory::setOptions($options);
             try {
                 //2. 发起API调用(以支付能力下的统一收单交易创建接口为例)
                 $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 '购买成功!';
    支付回调

    非必需,防止数据泄露被恶意调用接口。支付宝验签要将所有参数拼接成字符串验签,所以不要带入多余的参数。

  3. 通用版

    $params = $request->all();
    $config = config("alipay");
    $aop = new AlipayTradeService($config);
    $config = config("alipay");
    // 记得去除多余参数params
    if($aop->check($params))
    {
     echo '验签成功';
    }
  4. easy版

    $config = config('alipay');
    $params = $request->all();
    $Signer = new Signer();
    // 记得去除多余参数params
    $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支付
  1. 先申请公众号,然后配置公众号信息
 /*
     * 公众号
     */
    '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')
            ]
    ]
  1. 用接口获取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']);
}
// 获取code
$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);
  1. 用前面获取的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,
]);
// 未完待续
  1. WeixinJSBridge
    PHP

     $json = $jssdk->bridgeConfig($prepayId); // 返回 json 字符串,如果想返回数组,传第二个参数 false

    JavaScript

    
     WeixinJSBridge.invoke(
            'getBrandWCPayRequest', $json,
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                     // 使用以上方式判断前端返回,微信团队郑重提示:
                     // res.err_msg将在用户支付成功后返回
                     // ok,但并不保证它绝对可靠。
                }
            }
        );
  2. 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) {
            // 支付成功后的回调函数
        }
    });
  3. 小程序

    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币充值成功';
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!