当时接到这个需求,瞬间就想到了微信的小程序红包,后来大体翻了一下文档,觉得就是给这个需求量身定做的.在第一个30天流水失败后,找了个微信商户的合作公司,坐快车,2天开通了微信小程序红包,微信企业付款到零钱功能.
接下来就是开发了,主要是3个接口,发放红包,领取红包,和验证红包状态,4个步骤,发放红包,验证红包状态,领取红包,验证红包状态.这里是官方链接: https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.PHP?chapter=18_4&index=1
-
- 1. 发放红包,参数很多,我就不一一细说,可以看看官方的说明,我直接上代码
1) 为了方便请求,封装一个红包基类Red.PHP
-
-
-
- <?php
- namespace appapicontroller;
- /*
- * 微信支付:小程序红包接口
- */
- use thinkController;
- class Red extends Controller
- {
- private $sendurl = ‘https://api.mch.weixin.qq.com/mmpaymkttransfers/sendminiprogramhb’;//发放红包接口
- private $searchurl = ‘https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo’;//红包查询接口
- private $mch_id = ‘你的商户号’;//商户号
- private $wxappid = ‘你的公众账号appid’;//公众账号appid
- private $send_name = ‘随便写’;//商户名称
- private $total_num = 1;//红包发放总人数,默认都是1个
- private $notify_way = ‘MINI_PROGRAM_JSAPI’;//通知用户形式,这里不用改
- private $scene_id = ”;//发放红包使用场景,红包金额大于200时必传
- private $key=’你的秘钥’;//商户号支付钥匙
- /**
- * 发放红包
- * @param $mch_billno
- * @param $re_openid
- * @param $total_amount
- * @param $wishing
- * @param $act_name
- * @param $remark
- * @return mixed
- * @throws Exception
- */
- public function sendhb($mch_billno,$re_openid,$total_amount,$wishing,$act_name,$remark)
- {
- //随机字符串
- $nonce_str = $this->createNoncestr();
- $parameters = array(
- ‘nonce_str’ => $nonce_str,
- ‘mch_billno’ => $mch_billno,
- ‘mch_id’ => $this->mch_id,
- ‘wxappid’ => $this->wxappid,
- ‘send_name’ => $this->send_name,
- ‘re_openid’ => $re_openid,
- ‘total_amount’ => $total_amount,
- ‘total_num’ => $this->total_num,
- ‘wishing’ => $wishing,
- ‘act_name’ => $act_name,
- ‘remark’ => $remark,
- ‘notify_way’ => $this->notify_way,
- ‘scene_id’ => $this->scene_id
- );
- //生成签名,所有参数+key然后MD5
- $parameters[‘sign’] = $this->getSign($parameters);
- $xmlData = $this->arrayToXml($parameters);
- $curlres = $this->postXmlCurl($xmlData, $this->sendurl);
- $res = $this->xmlToArray($curlres);
- return $res;
- }
- /**
- * 根据订单号查询红包状态
- * @param $mch_billno
- * @param $mch_id
- * @param $appid
- * @return mixed
- * @throws Exception
- */
- public function searchhb($mch_billno,$mch_id,$appid)
- {
- //随机字符串
- $nonce_str = $this->createNoncestr();
- $parameters = array(
- ‘nonce_str’ => $nonce_str,
- ‘mch_billno’ => $mch_billno,
- ‘mch_id’ => $mch_id,
- ‘appid’ => $appid,
- ‘bill_type’ => ‘MCHT’
- );
- //生成签名,所有参数+key然后MD5
- $parameters[‘sign’] = $this->getSign($parameters);
- $xmlData = $this->arrayToXml($parameters);
- $curlres = $this->postXmlCurl($xmlData, $this->searchurl);
- $res = $this->xmlToArray($curlres);
- return $res;
- }
- private function postXmlCurl($xml, $url)
- {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- //设置header
- curl_setopt($ch, CURLOPT_HEADER, FALSE);
- //要求结果为字符串且输出到屏幕上
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
- //post提交方式
- curl_setopt($ch, CURLOPT_POST, TRUE);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
- curl_setopt($ch, CURLOPT_TIMEOUT, 20);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
- //证书的位置
- curl_setopt($ch, CURLOPT_SSLCERT, APP_PATH . ‘/certRed/apiclient_cert.pem’); //你的证书所在路径
- //证书key的位置
- curl_setopt($ch, CURLOPT_SSLKEY, APP_PATH . ‘/certRed/apiclient_key.pem’); //你的证书key所在路径
- //运行curl
- $data = curl_exec($ch);
- //返回结果
- if ($data) {
- curl_close($ch);
- return $data;
- } else {
- $error = curl_errno($ch);
- curl_close($ch);
- throw new Exception(“curl出错,错误码:$error”);
- }
- }
- //数组转换成xml
- private function arrayToXml($arr)
- {
- $xml = “”;
- foreach ($arr as $key => $val) {
- if (is_array($val)) {
- $xml .= “” . $this->arrayToXml($val) . “” . $key . “>”;
- } else {
- $xml .= “” . $val . “” . $key . “>”;
- }
- }
- $xml .= “”;
- return $xml;
- }
- //xml转换成数组
- private function xmlToArray($xml)
- {
- //禁止引用外部xml实体
- libxml_disable_entity_loader(true);
- $xmlstring = simplexml_load_string($xml, ‘SimpleXMLElement’, LIBXML_NOCDATA);
- $val = json_decode(json_encode($xmlstring), true);
- return $val;
- }
- //作用:产生随机字符串,不长于32位
- public function createNoncestr($length = 32)
- {
- $chars = “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”;
- $str = “”;
- for ($i = 0; $i
- $str .= substr($chars, mt_rand(0, strlen($chars) – 1), 1);
- }
- return $str;
- }
- //作用:生成签名
- public function getSign($Obj)
- {
- foreach ($Obj as $k => $v) {
- //不为空的参数才参与签名
- if (!empty($v)) {
- $Parameters[$k] = $v;
- }
- }
- //签名步骤一:按字典序排序参数
- ksort($Parameters);
- $String = $this->formatBizQueryParaMap($Parameters, false);
- //签名步骤二:在string后加入KEY
- $String = $String . “&key=” . $this->key;
- //签名步骤三:MD5加密
- $String = md5($String);
- //签名步骤四:所有字符转为大写
- $result = strtoupper($String);
- return $result;
- }
- //作用:格式化参数,签名过程需要使用
- private function formatBizQueryParaMap($paraMap, $urlencode)
- {
- $buff = “”;
- ksort($paraMap);
- foreach ($paraMap as $k => $v) {
- if ($urlencode) {
- $v = urlencode($v);
- }
- $buff .= $k . “=” . $v . “&”;
- }
- $reqPar = ”;
- if (strlen($buff) > 0) {
- $reqPar = substr($buff, 0, strlen($buff) – 1);
- }
- return $reqPar;
- }
- }
-
-
2). 在另外一个控制器,写个测试方法调用接口
-
-
-
-
- /**
- * 测试红包发放/红包查询接口
- * @param string $mch_billno 订单号
- * @param string $mch_id 商户号
- * @param string $appid appid
- * @throws Exception
- */
- public function test($mch_billno=”,$mch_id=”,$appid=”)
- {
- if ($mch_billno && $mch_id) { //查询红包状态
- $weixinpay = new Red();
- $res = $weixinpay->searchhb($mch_billno, $mch_id, $appid);
- print_r($res);
- } else { //发放红包
- $money = mt_rand(100, 999); //红包金额,测试金额1元~9.99元
- $mch_billno = date(“YmdHis”) . rand(100, 999);//商户订单号
- $re_openid = $this->openid;//用户openid
- $total_amount = $money;//付款金额,单位分
- $wishing = ‘恭喜’;//红包祝福语
- $act_name = ‘奖励’;//活动名称
- $remark = ‘您的专属红包’;//备注
- $weixinpay = new Red();
- $res = $weixinpay->sendhb($mch_billno, $re_openid, $total_amount, $wishing, $act_name, $remark);
- print_r($res);
- }
- }
-
-
-
3). 测试红包发放接口,尴尬,余额不足.这里提醒一下,刚开通小程序红包的朋友,一定要进行产品设置,限额限数限ip,我改一下金额再跑一下
第二次发放成功了,说明发放接口没问题
4). 测试红包验证接口,这次很顺利,请求成功,status对照文档看
-
-
- 2. 领取红包,这个动作要在小程序中调用,还是直接上代码
- 1). 这里我将领取红包的参数在方法里处理好,用接口返回到小程序
- $arr[‘appId’] = ‘你的appid’;
- $arr[‘timeStamp’] = ‘”‘.time().'”‘; //时间戳要转字符串格式
- $arr[‘package’] = ‘urlencode之后的package,这个参数在红包发放成功之后可获取’; //package要进行urlencode
- $weixinpay = new Red();
- $arr[‘nonceStr’] = $weixinpay->createNoncestr();
- $arr[‘paySign’] = $weixinpay->getSign($arr);
$arr[‘signType’] = ‘MD5’; //不参与签名加密
$this->success(‘发送成功’,$arr);
- 1). 这里我将领取红包的参数在方法里处理好,用接口返回到小程序
- 2. 领取红包,这个动作要在小程序中调用,还是直接上代码
-
2). 小程序端接口接收参数
//后端传参,前端调用sendBizRedPacket函数
httpGet(“/api/web/getRed”, function(res) {
if (res.code == 1) {
console.log(‘拆红包’);
wx. sendBizRedPacket ({
timeStamp: res.data.timeStamp, // 支付签名时间戳,
nonceStr: res.data.nonceStr, // 支付签名随机串,不长于 32 位
package: res.data.package, //扩展字段,由商户传入
signType: res.data.signType, // 签名方式,
paySign: res.data.paySign, // 支付签名
success:function(res){
console.log(‘成功’,res);
},
fail:function(res){
console.log(‘失败’,res);
},
complete:function(res){
console.log(‘结束’,res);
}
})
console.log(‘拆红包之后’);
}
})
3). 查看执行结果
4). gg,彩蛋时间到了,场景值不支持.有没有想到什么,目前小程序红包仅支持用户微信扫码打开小程序,进行红包领取
我是gg了,我们的业务要求是用户发布信息成功之后,触发红包发放功能.如果你的需求是营销拉新,扫码触发.恭喜你,直接复制粘贴吧,记得改参数
文章来源于互联网:记一次开发小程序红包的经历