介绍
看标题都知道是干啥的,不要扭扭捏捏了,直接进入吧
支付宝能力
action | 说明 | 返回值 |
---|---|---|
web | 网页支付 | Response |
app | APP支付 | Response |
h5 | H5支付 | Response |
scan | 二维码支付 | Collection |
pos | POS刷卡支付 | Collection |
mini | 小程序支付 | Collection |
transfer | 账户转账支付(暂时不考虑,场景太少) | Collection |
微信能力
action | 说明 | 返回值 |
---|---|---|
mp | 公众号支付 | Collection |
app | APP支付 | Collection |
h5 | H5支付 | Collection |
scan | 二维码支付 | Collection |
pos | POS刷卡支付 | Collection |
mini | 小程序支付 | Collection |
transfer | 账户转账支付(暂时不考虑,场景太少) | Collection |
开搞
1:使用 composer 下载安装支付扩展包
#laravel,lumen,hyperf 安装方式
composer require yansongda/pay:~3.7.0 -vvv
#无框架或者其他框架安装方式
composer require yansongda/pay:~3.7.0 -vvv
composer require guzzlehttp/guzzle:^7.0 #其他框架如果有此插件,可以不用安装
composer require hyperf/pimple:~2.2.0 #主要是 Container 复用
注意:
如果使用的框架内有符合 PSR-11 的 Container,需要在初始化之前,先调用以下代码以复用 Container,进行服务注入
<?php
use Yansongda\Pay\Pay;
use Yansongda\Pay\Contract\HttpClientInterface;
// $container = 您现有的 container
// 方法一:
Pay::setContainer($container);
Pay::config($config);
// 方法二:
Pay::config($config, function () use ($container) {
return $container;
});
2:初始化支付参数
1:在 config 文件夹下新建 alipay.php 文件 (laravel框架,其他的自行找地方配置吧,能取出就行)
<?php
return [
'alipay' => [
'default' => [
// 必填-支付宝分配的 app_id
'app_id' => 'xxxxxxx',
// 必填-应用私钥 字符串或路径
// 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
'app_secret_cert' => 'xxxxxx',
// 必填-应用公钥证书 路径
// 设置应用私钥后,即可下载得到以下3个证书
'app_public_cert_path' => '/xxxx/appCertPublicKey_2016082000295641.crt',
// 必填-支付宝公钥证书 路径
'alipay_public_cert_path' => '/xxxx/alipayCertPublicKey_RSA2.crt',
// 必填-支付宝根证书 路径
'alipay_root_cert_path' => '/xxxx/alipayRootCert.crt',
'return_url' => 'https://xxxxx',//同步返回地址
'notify_url' => 'https://xxxxx',//异步回调地址
// 选填-第三方应用授权token
'app_auth_token' => '',
// 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
'service_provider_id' => '',
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
'mode' => 'MODE_NORMAL',
]
],
'logger' => [ //日志模块,也可以在 logging.php 里自定义 channel 进行手动日志搜集
'enable' => false,
'file' => storage_path('logs/alipay.log'),
'level' => 'info',
'type' => 'daily',
'max_file' => 10,
],
'http' => [
'timeout' => 5.0,
'connect_timeout' => 5.0,
],
];
2:在 config 文件夹下新建 wechat.php 文件 (laravel框架,其他的自行找地方配置吧,能取出就行)
<?php
return [
'wechat' => [
'default' => [
// 必填-商户号,服务商模式下为服务商商户号
// 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
'mch_id' => '',
// 选填-v2商户私钥
'mch_secret_key_v2' => '',
// 必填-v3 商户秘钥
// 即 API v3 密钥(32字节,形如md5值),可在 账户中心->API安全 中设置
'mch_secret_key' => '',
// 必填-商户私钥 字符串或路径
// 即 API证书 PRIVATE KEY,可在 账户中心->API安全->申请API证书 里获得
// 文件名形如:apiclient_key.pem
'mch_secret_cert' => '',
// 必填-商户公钥证书路径
// 即 API证书 CERTIFICATE,可在 账户中心->API安全->申请API证书 里获得
// 文件名形如:apiclient_cert.pem
'mch_public_cert_path' => '',
// 必填-微信回调url
// 不能有参数,如?号,空格等,否则会无法正确回调
'notify_url' => 'https://xxxx',
// 选填-公众号 的 app_id
// 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
'mp_app_id' => 'xxxxx',
// 选填-小程序 的 app_id
'mini_app_id' => '',
// 选填-小程序的 app_secret
'mini_app_secret' => '',
// 选填-app 的 app_id
'app_id' => '',
// 选填-服务商模式下,子公众号 的 app_id
'sub_mp_app_id' => '',
// 选填-服务商模式下,子 app 的 app_id
'sub_app_id' => '',
// 选填-服务商模式下,子小程序 的 app_id
'sub_mini_app_id' => '',
// 选填-服务商模式下,子商户id
'sub_mch_id' => '',
// 选填-微信平台公钥证书路径, optional,强烈建议 php-fpm 模式下配置此参数
'wechat_public_cert_path' => [
'45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatPublicKey.crt',
],
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
'mode' => 'MODE_NORMAL',
//小程序授权登录,通过code换取openid和sessionkey的接口
'jscode2session_url'=> 'https://api.weixin.qq.com/sns/jscode2session',
//小程序通过sessionkey和其他加密参数解析获取手机号的接口
'decrypt_phone_url'=> 'https://api.weixin.qq.com/wxa/business/getuserphonenumber',
]
],
'logger' => [
'enable' => false,
'file' => storage_path('logs/wechat.log'),
'level' => 'info',
'type' => 'daily',
'max_file' => 10,
],
'http' => [ // optional
'timeout' => 5.0,
'connect_timeout' => 5.0,
]
];
3:开始接入支付----支付宝
1:例如,我的订单信息为:
$order = [
"out_trade_no" => "1234567890", #你自己的业务订单号
"total_amount" => 1200, #订单金额,单位 分
"order_name" => "汤臣一品5号楼12层订单_小可爱", #订单名称/描述
]
2:在一个你喜欢的目录里封装一个类:例如 app/Services/AlipayService.php
<?php
namespace App\Services;
use App\Common\Functions;
use Illuminate\Support\Facades\Redis;
use Yansongda\Pay\Pay;
class AlipayService
{
//网页网站支付
public static function webPay($order){
Pay::config(Config('alipay'));
$data = Pay::alipay()->web([
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name'],
]);
return $data;
// 获取跳转代码(表单形式) return (string) $data->getBody();
}
//h5支付
public static function h5Pay($order){
Pay::config(Config('alipay'));
return Pay::alipay()->h5([
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name'],
'quit_url' => 'https://xxxxxx',
]);
}
//app支付
public static function appPay($order){
Pay::config(Config('alipay'));
return Pay::alipay()->app([
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name'],
]);
}
//小程序支付
public static function miniPay($order){
Pay::config(Config('alipay'));
$result = Pay::alipay()->mini([
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name'],
'buyer_id' => '1111223232323', #当前购买用户在此小程序下的id
]);
return $result->get('trade_no'); // 支付宝交易号
}
//pos支付
public static function posPay($order){
Pay::config(Config('alipay'));
$result = Pay::alipay()->pos([
'out_trade_no' => $order['out_trade_no'],
'auth_code' => 'xxxxxxx', #授权code码
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name']
]);
return $result;
}
//扫码支付
public static function scanPay($order){
Pay::config(Config('alipay'));
$result = Pay::alipay()->pos([
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount']/100,
'subject' => $order['order_name']
]);
return $result->qr_code; // 二维码 url,前端直接渲染出来就可以
}
//查询订单
public static function findOrder($outTradeNo, $type){
if (!in_array($type, ['web','app','h5','scan','pos','mini'])) {
return false;
}
Pay::config(Config('alipay'));
$result = Pay::alipay()->query([
'out_trade_no' => $outTradeNo,
'_action' => $type
]);
return $result;
}
//查询退款订单
public static function findRefundOrder($outTradeNo,$outRequestNo, $type){
if (!in_array($type, ['web','app','h5','scan','pos','mini'])) {
return false;
}
Pay::config(Config('alipay'));
$result = Pay::alipay()->query([
'out_trade_no' => $outTradeNo,
'out_request_no' => $outRequestNo,
'_action' => 'redund_'.$type
]);
return $result;
}
//退款
public static function refundOrder($outTradeNo, $type){
if (!in_array($type, ['web','app','h5','scan','pos','mini'])) {
return false;
}
Pay::config(Config('alipay'));
$result = Pay::alipay()->refund([
'out_trade_no' => $outTradeNo,
'refund_amount' => '0.01',
'_action' => 'redund_'.$type
]);
return $result;
}
}
3:支付宝回调
public function alipayNotify(Request $request){
Pay::config(Config('alipay'));
$result = Pay::alipay()->callback();
//然后你就开始处理result结果吧,并处理你得业务逻辑
}
4:开始接入支付---- 微信
1:例如,我的订单信息为:
$order = [
"out_trade_no" => "1234567890", #你自己的业务订单号
"total_amount" => 1200, #订单金额,单位 分
"order_name" => "后海四合院一套_大可爱", #订单名称/描述
]
2:在一个你喜欢的目录里封装一个类:例如 app/Services/WechatService.php
<?php
namespace App\Services;
use App\Common\Functions;
use Illuminate\Support\Facades\Redis;
use Yansongda\Pay\Pay;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Http;
class WechatService
{
//公众号支付
public static function mpPay($order){
Pay::config(Config('wechat'));
$payOrder = [
'out_trade_no' => $order['out_trade_no'],
'description' => $order['order_name'],
'amount' => [
'total' => int($order['total_amount']),
],
'payer' => [
//这个是微信用户在此公众号下的唯一标识openid,可以通过微信支付官方文档获取https://pay.weixin.qq.com/docs/partner/development/glossary/parameter.html
'openid' => 'onkVf1FjWS5SBxxxxxxxx',
],
];
$result = Pay::wechat()->mp($payOrder);
// 返回 Collection 实例。包含了调用 JSAPI 的所有参数,如appId,timeStamp,nonceStr,package,signType,paySign 等;
// 可直接通过 $result->appId, $result->timeStamp 获取相关值
}
//h5支付
public static function h5Pay($order){
Pay::config(Config('wechat'));
$payOrder = [
//'_type' => 'mini', // 如果关联的小程序appid,需要加上这一行;关联的公众号的则不需要
'out_trade_no' => $order['out_trade_no'],
'description' => $order['order_name'],
'amount' => [
'total' => $order['total_amount'],
],
'scene_info' => [
'payer_client_ip' => '',
'h5_info' => [
'type' => 'Wap',
]
],
];
return Pay::wechat()->h5($payOrder);
}
//app支付
public static function appPay($order){
Pay::config(Config('wechat'));
$payOrder = [
'out_trade_no' => $order['out_trade_no'],
'description' => $order['order_name'],
'amount' => [
'total' => $order['total_amount'],
],
];
return Pay::wechat()->app($payOrder);
}
//小程序支付
public static function miniPay($order){
Pay::config(Config('wechat'));
$payOrder = [
'out_trade_no' => $order['out_trade_no'],
'description' => $order['order_name'],
'amount' => [
'total' => $order['total_amount'],
'currency' => 'CNY',
],
'payer' => [
'openid' => '123fsdf234', //用户在小程序下的openid,下面有获取的方法,decryptMiniCode
]
];
$result = Pay::wechat()->mini($payOrder);
// 返回 Collection 实例。包含了调用JSAPI的所有参数,如appId,timeStamp,nonceStr,package,signType,paySign 等;
// 可直接通过 $result->appId, $result->timeStamp 获取相关值。
}
//扫码支付
public static function scanPay($order){
Pay::config(Config('wechat'));
$payOrder = [
'out_trade_no' => $order['out_trade_no'],
'description' => $order['order_name'],
'amount' => [
'total' => $order['total_amount'],
],
];
$result = Pay::wechat()->scan($payOrder);
return $result->code_url; // 二维码内容
}
/**
* 查询订单
*/
public static function findOrder($outTradeNo = '', $type){
if (!in_array($type,['jsapi','app','combine','h5','miniapp','native'])) {
return false;
}
Pay::config(Config('wechat'));
$result = Pay::wechat()->query([
'out_trade_no' => $outTradeNo,
'_action' => $type
]);
return $result;
}
//订单退款
public static function refundOrder($orderTradeNo, $type, $refundId = ''){
if (!in_array($type,['jsapi','app','combine','h5','miniapp','native'])) {
return false;
}
Pay::config(Config('wechat'));
$result = Pay::wechat()->refund([
'out_trade_no' => $orderTradeNo,
'out_refund_no' => $refundId ?? 'refund_wechat_id_'.time(),
'amount' => [
'refund' => 1,
'total' => 1,
'currency' => 'CNY'
],
'_action' => $type
]);
return $result;
}
//小程序授权登录获取openid,seesion_key,文档链接:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
public static function decryptMiniCode($code){
$config = Config('wechat')['wechat']['default'];
$result = Http::asForm()->post($config['jscode2session_url'],[
'appid' => $config['mini_app_id'],
'secret' => $config['mini_app_secret'],
'js_code' => $code, //登录时获取的 code,可通过wx.login获取
'grant_type' => 'authorization_code'
]);
return $result->successful() ? $result->json() : [];
}
}
2:微信回调
public function wechatNotify(Request $request){
Pay::config(Config('wechat'));
$result = Pay::wechat()->callback();
}