php实现微信支付之现金红包


Posted in PHP onMay 30, 2018

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

直接运行该文件即可给指定的微信用户发送现金红包。

需要注意的事项:

1.微信现金红包要求必传证书,需要到这里 账户中心->账户设置->API安全->下载证书,然后修改代码中的证书路径

2.默认的使用场景是抽奖(即scene_id参数为PRODUCT_2),额度是1-200元,所以测试时的最低金额是1元。如需修改在产品中心->产品大全->现金红包->产品设置中修改

3.该文件需放到支付授权目录下,可以在微信支付商户平台->产品中心->开发配置中设置。

4.如提示签名错误可以通过微信支付签名验证工具进行验证:微信公众平台支付接口调试工具

5.错误码参照 :地址

代码如下:

<?php
/**
 * 关于微信现金红包的说明
 * 1.微信现金红包要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,证书路径在第214行和217行修改
 * 2.默认的使用场景是抽奖(即scene_id参数为PRODUCT_2),额度是1-200元,所以测试时的最低金额是1元。如需修改在产品中心->产品大全->现金红包->产品设置中修改
 * 3.错误码参照 :https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
 */
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;  //红包金额,单位:元
$sendName = '织梦猫'; //红包发送者名称
$wishing = '感谢您参加猜灯谜活动,祝您元宵节快乐!'; //红包祝福语
$act_name='猜灯谜抢红包活动';  //活动名称
$result = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$sendName,$wishing,$act_name);
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 $wishing 祝福语
 * @param string $actName 互动名称
 * @return string
 */
 public function createJsBizPackage($openid, $totalFee, $outTradeNo, $sendName,$wishing,$actName)
 {
 $config = array(
  'mch_id' => $this->mchid,
  'appid' => $this->appid,
  'key' => $this->apiKey,
 );
 $unified = array(
  'wxappid' => $config['appid'],
  'send_name' => $sendName,
  'mch_id' => $config['mch_id'],
  'nonce_str' => self::createNonceStr(),
  're_openid' => $openid,
  'mch_billno' => $outTradeNo,
  'client_ip' => '127.0.0.1',
  'total_amount' => intval($totalFee * 100), //单位 转为分
  'total_num'=>1,   //红包发放总人数
  'wishing'=>$wishing,  //红包祝福语
  'act_name'=>$actName,  //活动名称
  'remark'=>'remark',  //备注信息,如为中文注意转为UTF8编码
  'scene_id'=>'PRODUCT_2', //发放红包使用场景,红包金额大于200时必传。https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
 );
 $unified['sign'] = self::getSign($unified, $config['key']);
 $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack', 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下载地址:weixinPay

相关文章:

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

PHP 相关文章推荐
PHP脚本的10个技巧(6)
Oct 09 PHP
实现 win2003 下 mysql 数据库每天自动备份
Dec 06 PHP
php 获取完整url地址
Dec 20 PHP
不支持fsockopen但支持culr环境下下ucenter与modoer通讯问题
Aug 12 PHP
PHP ? EasyUI DataGrid 资料存的方式介绍
Nov 07 PHP
关于php 接口问题(php接口主要也就是运用curl,curl函数)
Jul 01 PHP
php 检查电子邮件函数(自写)
Jan 16 PHP
PHP实现中文圆形印章特效
Jun 19 PHP
PHP读取PPT文件的方法
Dec 10 PHP
CodeIgniter框架验证码类库文件与用法示例
Mar 18 PHP
PHP写的简单数字验证码实例
May 23 PHP
php微信开发之音乐回复功能
Jun 14 PHP
php微信支付之公众号支付功能
May 30 #PHP
php实现微信原生支付(扫码支付)功能
May 30 #PHP
php实现支付宝当面付(扫码支付)功能
May 30 #PHP
PHP ADODB生成HTML表格函数rs2html功能【附错误处理函数用法】
May 29 #PHP
PHP ADODB生成下拉列表框功能示例
May 29 #PHP
Laravel实现短信注册的示例代码
May 29 #PHP
PHP abstract 抽象类定义与用法示例
May 29 #PHP
You might like
php获取四位字母和数字的随机数的实现方法
2015/01/09 PHP
php保存信息到当前Session的方法
2015/03/16 PHP
php轻松实现文件上传功能
2016/03/03 PHP
ExtJS 工具栏 分页事件参数
2010/03/05 Javascript
关于全局变量和局部变量的那些事
2013/01/11 Javascript
iframe的父子窗口之间的对象相互调用基本用法
2013/09/03 Javascript
JavaScript如何从listbox里同时删除多个项目
2013/10/12 Javascript
ExtJS如何设置与获取radio控件的选取状态
2014/01/22 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
2014/09/26 Javascript
jQuery修改li下的样式以及li下的img的src的值的方法
2014/11/02 Javascript
本人自用的global.js库源码分享
2015/02/28 Javascript
jQuery控制元素显示、隐藏、切换、滑动的方法总结
2015/04/16 Javascript
详解nodejs 文本操作模块-fs模块(二)
2016/12/22 NodeJs
JavaScript中document.referrer的用法详解
2017/07/04 Javascript
bootstrap表格内容过长时用省略号表示的解决方法
2017/11/21 Javascript
JS生成随机打乱数组的方法示例
2017/12/23 Javascript
使用vue2实现购物车和地址选配功能
2018/03/29 Javascript
JS中使用cavas截图网页并解决跨域及模糊问题
2018/11/13 Javascript
微信小程序人脸识别功能代码实例
2019/05/07 Javascript
使用Vue实现移动端左滑删除效果附源码
2019/05/16 Javascript
基于Node.js的大文件分片上传示例
2019/06/19 Javascript
layui--js控制switch的切换方法
2019/09/03 Javascript
JavaScript获取某一天所在的星期
2019/09/05 Javascript
在vue中把含有html标签转为html渲染页面的实例
2019/10/28 Javascript
python爬取网站数据保存使用的方法
2013/11/20 Python
Python获取暗黑破坏神3战网前1000命位玩家的英雄技能统计
2016/07/04 Python
用python 批量更改图像尺寸到统一大小的方法
2018/03/31 Python
使用python远程操作linux过程解析
2019/12/04 Python
python 用opencv实现图像修复和图像金字塔
2020/11/27 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
html5 实现客户端验证上传文件的大小(简单实例)
2016/05/15 HTML / CSS
DNA基因检测和分析:23andMe
2019/05/01 全球购物
印度尼西亚最完整和最大的在线药房网站:Farmaku.com
2019/11/23 全球购物
毕业生自荐书
2014/02/02 职场文书
2015年远程教育工作总结
2015/05/20 职场文书
2016年幼儿园庆六一开幕词
2016/03/04 职场文书