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 相关文章推荐
详细介绍:Apache+PHP+MySQL配置攻略
Sep 05 PHP
PHP 魔术函数使用说明
May 14 PHP
php中禁止单个IP与ip段访问的代码小结
Jul 04 PHP
php全排列递归算法代码
Oct 09 PHP
php使用imagick模块实现图片缩放、裁剪、压缩示例
Apr 17 PHP
从刷票了解获得客户端IP的方法
Sep 21 PHP
Yii中创建自己的Widget实例
Jan 05 PHP
PHP Ajax JavaScript Json获取天气信息实现代码
Aug 17 PHP
php实现文章置顶功能的方法
Oct 20 PHP
php实现背景图上添加圆形logo图标的方法
Nov 17 PHP
PHP获取真实客户端的真实IP
Mar 07 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
Jun 11 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连mysql和oracle数据库性能比较
2006/10/09 PHP
php debug 安装技巧
2011/04/30 PHP
WordPress中缩略图的使用以及相关技巧
2015/11/24 PHP
PHP 自动加载的简单实现(推荐)
2016/08/12 PHP
php+js实现裁剪任意形状图片
2018/10/31 PHP
php array 转json及java 转换 json数据格式操作示例
2019/11/13 PHP
通过 Dom 方法提高 innerHTML 性能
2008/03/26 Javascript
javascript 事件处理、鼠标拖动效果实现方法详解
2012/05/11 Javascript
jQuery easyui datagrid动态查询数据实例讲解
2013/02/26 Javascript
客户端js性能优化小技巧整理
2013/11/05 Javascript
jquery 按键盘上的enter事件
2014/05/11 Javascript
兼容最新firefox、chrome和IE的javascript图片预览实现代码
2014/08/08 Javascript
简单谈谈gulp-changed插件
2017/02/21 Javascript
vue.js 1.x与2.0中js实时监听input值的变化
2017/03/15 Javascript
详解用node-images 打造简易图片服务器
2017/05/08 Javascript
AngularJS实现的获取焦点及失去焦点时的表单验证功能示例
2017/10/25 Javascript
react中Suspense的使用详解
2019/09/01 Javascript
vue el-table实现自定义表头
2019/12/11 Javascript
js实现点赞效果
2020/03/16 Javascript
从零学Python之引用和类属性的初步理解
2014/05/15 Python
Python处理字符串之isspace()方法的使用
2015/05/19 Python
Python创建字典的八种方式
2019/02/27 Python
Python从函数参数类型引出元组实例分析
2019/05/28 Python
Python使用grequests(gevent+requests)并发发送请求过程解析
2019/09/25 Python
Python爬虫基于lxml解决数据编码乱码问题
2020/07/31 Python
详解CSS3:overflow属性
2020/11/17 HTML / CSS
HTML5 canvas画图并保存成图片的jcanvas插件
2014/01/17 HTML / CSS
解释一下钝化(Swap out)
2016/12/26 面试题
护士个人简历自荐信
2013/10/18 职场文书
毕业生找工作的自我评价
2013/10/18 职场文书
高分子材料与工程专业推荐信
2013/12/01 职场文书
初一地理教学反思
2014/01/16 职场文书
《金钱的魔力》教学反思
2014/02/24 职场文书
品牌推广活动策划方案
2014/08/19 职场文书
用人单位终止解除劳动合同证明书
2014/10/06 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书