php实现微信支付之企业付款


Posted in PHP onMay 30, 2018

网上的很多PHP微信支付接入教程都颇为复杂,且需要配置和引入较多的文件,本人通过整理后给出一个单文件版的,希望可以给各位想接入微信支付的带来些许帮助和借鉴意义。

直接运行该文件即可给指定的微信用户转账。

需要注意的事项:

1.微信企业付款到零钱要求必传证书,需要到这里账户中心->账户设置->API安全->下载证书,然后修改代码中的证书路径 
2.该文件需放到支付授权目录下,可以在微信支付商户平台->产品中心->开发配置中设置。
3.如提示签名错误可以通过微信支付签名验证工具进行验证:微信公众平台支付接口调试工具
4.错误码参照:参照地址

代码如下:

<?php
/**
 * 关于微信企业付款的说明
 * 1.微信企业付款要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,证书路径在第207行和210行修改
 * 2.错误码参照 :https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
 */
header('Content-type:text/html; Charset=utf-8');
$mchid = 'xxxxx';  //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送
$appid = 'xxxxx'; //微信支付申请对应的公众号的APPID
$appKey = 'xxxxx'; //微信支付申请对应的公众号的APP Key
$apiKey = 'xxxxx'; //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥

//①、获取当前访问页面的用户openid(如果给指定用户转账,则直接填写指定用户的openid)
$wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey);
$openId = $wxPay->GetOpenid(); //获取openid
if(!$openId) exit('获取openid失败');
//②、付款
$outTradeNo = uniqid(); //订单号
$payAmount = 1;  //转账金额,单位:元。转账最小金额为1元
$trueName = '张三';  //收款人真实姓名
$result = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$trueName);
echo 'success';
class WxpayService
{
 protected $mchid;
 protected $appid;
 protected $appKey;
 protected $apiKey;
 public $data = null;

 public function __construct($mchid, $appid, $appKey,$key)
 {
 $this->mchid = $mchid;
 $this->appid = $appid;
 $this->appKey = $appKey;
 $this->apiKey = $key;
 }

 /**
 * 通过跳转获取用户的openid,跳转流程如下:
 * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
 * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
 * @return 用户的openid
 */
 public function GetOpenid()
 {
 //通过code获得openid
 if (!isset($_GET['code'])){
  //触发微信返回code码
  $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://';
  $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']);
  $url = $this->__CreateOauthUrlForCode($baseUrl);
  Header("Location: $url");
  exit();
 } else {
  //获取code码,以获取openid
  $code = $_GET['code'];
  $openid = $this->getOpenidFromMp($code);
  return $openid;
 }
 }

 /**
 * 通过code从工作平台获取openid机器access_token
 * @param string $code 微信跳转回来带上的code
 * @return openid
 */
 public function GetOpenidFromMp($code)
 {
 $url = $this->__CreateOauthUrlForOpenid($code);
 $res = self::curlGet($url);
 //取出openid
 $data = json_decode($res,true);
 $this->data = $data;
 $openid = $data['openid'];
 return $openid;
 }

 /**
 * 构造获取open和access_toke的url地址
 * @param string $code,微信跳转带回的code
 * @return 请求的url
 */
 private function __CreateOauthUrlForOpenid($code)
 {
 $urlObj["appid"] = $this->appid;
 $urlObj["secret"] = $this->appKey;
 $urlObj["code"] = $code;
 $urlObj["grant_type"] = "authorization_code";
 $bizString = $this->ToUrlParams($urlObj);
 return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
 }

 /**
 * 构造获取code的url连接
 * @param string $redirectUrl 微信服务器回跳的url,需要url编码
 * @return 返回构造好的url
 */
 private function __CreateOauthUrlForCode($redirectUrl)
 {
 $urlObj["appid"] = $this->appid;
 $urlObj["redirect_uri"] = "$redirectUrl";
 $urlObj["response_type"] = "code";
 $urlObj["scope"] = "snsapi_base";
 $urlObj["state"] = "STATE"."#wechat_redirect";
 $bizString = $this->ToUrlParams($urlObj);
 return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
 }

 /**
 * 拼接签名字符串
 * @param array $urlObj
 * @return 返回已经拼接好的字符串
 */
 private function ToUrlParams($urlObj)
 {
 $buff = "";
 foreach ($urlObj as $k => $v)
 {
  if($k != "sign") $buff .= $k . "=" . $v . "&";
 }
 $buff = trim($buff, "&");
 return $buff;
 }

 /**
 * 企业付款
 * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid
 * @param float $totalFee 收款总费用 单位元
 * @param string $outTradeNo 唯一的订单号
 * @param string $orderName 订单名称
 * @param string $notifyUrl 支付结果通知url 不要有问号
 * @param string $timestamp 支付时间
 * @return string
 */
 public function createJsBizPackage($openid, $totalFee, $outTradeNo,$trueName)
 {
 $config = array(
  'mch_id' => $this->mchid,
  'appid' => $this->appid,
  'key' => $this->apiKey,
 );
 $unified = array(
  'mch_appid' => $config['appid'],
  'mchid' => $config['mch_id'],
  'nonce_str' => self::createNonceStr(),
  'openid' => $openid,
  'check_name'=>'FORCE_CHECK', //校验用户姓名选项。NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名
  're_user_name'=>$trueName,   //收款用户真实姓名(不支持给非实名用户打款)
  'partner_trade_no' => $outTradeNo,
  'spbill_create_ip' => '127.0.0.1',
  'amount' => intval($totalFee * 100), //单位 转为分
  'desc'=>'付款',  //企业付款操作说明信息
 );
 $unified['sign'] = self::getSign($unified, $config['key']);
 $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers', self::arrayToXml($unified));
 $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
 if ($unifiedOrder === false) {
  die('parse xml error');
 }
 if ($unifiedOrder->return_code != 'SUCCESS') {
  die($unifiedOrder->return_msg);
 }
 if ($unifiedOrder->result_code != 'SUCCESS') {
  die($unifiedOrder->err_code);
 }
 return true;
 }

 public static function curlGet($url = '', $options = array())
 {
 $ch = curl_init($url);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 if (!empty($options)) {
  curl_setopt_array($ch, $options);
 }
 //https请求 不验证证书和host
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
 $data = curl_exec($ch);
 curl_close($ch);
 return $data;
 }

 public function curlPost($url = '', $postData = '', $options = array())
 {
 if (is_array($postData)) {
  $postData = http_build_query($postData);
 }
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_POST, 1);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
 curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
 if (!empty($options)) {
  curl_setopt_array($ch, $options);
 }
 //https请求 不验证证书和host
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

 //第一种方法,cert 与 key 分别属于两个.pem文件
 //默认格式为PEM,可以注释
 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
 curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/cert/apiclient_cert.pem');
 //默认格式为PEM,可以注释
 curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
 curl_setopt($ch,CURLOPT_SSLKEY,getcwd().'/cert/apiclient_key.pem');
 //第二种方式,两个文件合成一个.pem文件
// curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');
 $data = curl_exec($ch);
 curl_close($ch);
 return $data;
 }

 public static function createNonceStr($length = 16)
 {
 $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 $str = '';
 for ($i = 0; $i < $length; $i++) {
  $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
 }
 return $str;
 }
 public static function arrayToXml($arr)
 {
 $xml = "<xml>";
 foreach ($arr as $key => $val) {
  if (is_numeric($val)) {
  $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  } else
  $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
 }
 $xml .= "</xml>";
 return $xml;
 }

 public static function getSign($params, $key)
 {
 ksort($params, SORT_STRING);
 $unSignParaString = self::formatQueryParaMap($params, false);
 $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
 return $signStr;
 }
 protected static function formatQueryParaMap($paraMap, $urlEncode = false)
 {
 $buff = "";
 ksort($paraMap);
 foreach ($paraMap as $k => $v) {
  if (null != $v && "null" != $v) {
  if ($urlEncode) {
   $v = urlencode($v);
  }
  $buff .= $k . "=" . $v . "&";
  }
 }
 $reqPar = '';
 if (strlen($buff) > 0) {
  $reqPar = substr($buff, 0, strlen($buff) - 1);
 }
 return $reqPar;
 }
}
?>

github下载地址

相关文章:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP 向右侧拉菜单实现代码,测试使用中
Nov 03 PHP
php 图片加水印与上传图片加水印php类
May 12 PHP
PHP数组及条件,循环语句学习
Nov 11 PHP
如何批量替换相对地址为绝对地址(利用bat批处理实现)
May 27 PHP
php去除字符串换行符示例分享
Feb 13 PHP
Linux下PHP连接Oracle数据库
Aug 20 PHP
Yii框架组件和事件行为管理详解
May 20 PHP
Yii多表联合查询操作详解
Jun 02 PHP
PHP Cookie学习笔记
Aug 23 PHP
PHP容器类的两种实现方式示例
Jul 24 PHP
PHP基于timestamp和nonce实现的防止重放攻击方案分析
Jul 26 PHP
laravel自定义分页的实现案例offset()和limit()
Oct 15 PHP
ThinkPHP5框架缓存查询操作分析
May 30 #PHP
PHP实现通过CURL上传文件功能示例
May 30 #PHP
php实现微信支付之现金红包
May 30 #PHP
php微信支付之公众号支付功能
May 30 #PHP
php实现微信原生支付(扫码支付)功能
May 30 #PHP
php实现支付宝当面付(扫码支付)功能
May 30 #PHP
PHP ADODB生成HTML表格函数rs2html功能【附错误处理函数用法】
May 29 #PHP
You might like
PHP用户注册邮件激活账户的实现代码
2017/05/31 PHP
php pdo连接数据库操作示例
2019/11/18 PHP
JS 文件传参及处理技巧分析
2010/05/13 Javascript
js打印纸函数代码(递归)
2010/06/18 Javascript
Jquery中获取iframe的代码
2011/01/11 Javascript
Jquery解析Json格式数据过程代码
2014/10/17 Javascript
使用Node.js为其他程序编写扩展的基本方法
2015/06/23 Javascript
详解AngularJS 模态对话框
2016/04/07 Javascript
Vue.JS入门教程之事件监听
2016/12/01 Javascript
浅谈struts1 &amp; jquery form 文件异步上传
2017/05/25 jQuery
js 概率计算(简单版)
2017/09/12 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
2017/10/20 Javascript
解决vue A对象赋值给B对象,修改B属性会影响到A的问题
2018/09/25 Javascript
详解基于node.js的脚手架工具开发经历
2019/01/28 Javascript
node.js微信小程序配置消息推送的实现
2019/02/13 Javascript
vue实现记事本功能
2019/06/26 Javascript
微信小程序实现图片选择并预览功能
2019/07/25 Javascript
vue实现吸顶、锚点和滚动高亮按钮效果
2019/10/21 Javascript
mustache.js实现首页元件动态渲染的示例代码
2020/12/28 Javascript
python爬虫_自动获取seebug的poc实例
2017/08/05 Python
python的Tqdm模块的使用
2018/01/10 Python
使用python进行拆分大文件的方法
2018/12/10 Python
使用Django搭建网站实现商品分页功能
2020/05/22 Python
python算的上脚本语言吗
2020/06/22 Python
html5 Canvas画图教程(1)—画图的基本常识
2013/01/09 HTML / CSS
PHP两种查询函数array/row的区别
2013/06/03 面试题
门卫岗位职责
2013/11/15 职场文书
开展党的群众路线教育实践活动方案
2014/02/05 职场文书
竞争上岗实施方案
2014/03/21 职场文书
询价采购方案
2014/06/09 职场文书
中学生旷课检讨书2篇
2014/10/09 职场文书
追讨欠款律师函
2015/06/24 职场文书
民间借贷纠纷答辩状
2015/08/03 职场文书
Python基础知识学习之类的继承
2021/05/31 Python
使用CSS3实现按钮悬停闪烁动态特效代码
2021/08/30 HTML / CSS
Python爬虫 简单介绍一下Xpath及使用
2022/04/26 Python