小程序發微信紅包後端Nodejs實現

前提條件html

一、有一個微信開放平臺 https://open.weixin.qq.com/node

二、有一個微信公衆平臺 https://mp.weixin.qq.com  而且開通微信支付小程序

三、有一個微信小程序 https://developers.weixin.qq.com/miniprogram/dev/quickstart/basic/release.html 登錄地址同 2 微信公衆平臺後端

申請過程就不詳細說了,準備好各類企業的資質證書,運營執照,企業版 須要對公帳戶打款驗證 微信小程序

小程序要綁定到公衆號,公衆號和小程序都要綁定到開放平臺api

說一下爲何要有這三個平臺帳號,原平生臺app 拉起微信小程序,受權登錄之後取得登陸碼,受權登陸官方文檔 https://developers.weixin.qq.com/miniprogram/dev/api/wx.login.html服務器

把這個登陸碼發送到後端,後端經過這個登陸碼+小程序的appid + secret 拿到用戶的unionid(小程序 和 公衆號 都要綁定了開放平臺纔會有unionid,同一開放平臺下的小程序和公衆號unionid相同) 微信

獲取unionid官方文檔 https://developers.weixin.qq.com/miniprogram/dev/api/code2Session.htmlapp

經過這個unionid來獲取到玩家在公衆號的openid,微信支付發送紅包到玩家帳號上就是經過這個公衆號的openid微信公衆平臺

後端必定要配置一個https的服務器 否則發微信紅包的時候 只會收到微信服務器返回 302 not fond

Node 環境https的配置 https://blog.csdn.net/wufaliang003/article/details/77478720

下面直接上代碼了

輔助函數部分

let crypto = require("crypto");

exports.MgetMD5 = function(str){
    let hash = crypto.createHash('md5');
    let md5Value = hash.update(str).digest("hex");
    return md5Value.toUpperCase()
}

exports.MgetSHA256 = function(str,key){
    let hmac = crypto.createHmac('sha256',key);
    let shaValue = hmac.update(str).digest("hex");
    return shaValue.toUpperCase();
}

let charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklnmopqrstuvwxyz0123456789";
//返回隨機字符串
exports.MgetRandomStr = function(length){
    if (length){
        length = Math.round(length);
    }
    else{
        length = Math.round(Math.random()*20 + 12)
    }
    let range = charSet.length;
    let result = '';
    let position = 0;
    for(let i = 0; i < length; i++)
    {   position = Math.floor(Math.random()*range);
        result += charSet[position];
    }
    return result;
}


//返回隨機數字字符串
exports.MgetRandomNumber = function(length){
    let numbers = '0123456789';
    length = length ? length : 10;
    let range = numbers.length;
    let result = '';
    let position = 0;
    for(let i = 0; i < length; i++)
    {   position = Math.floor(Math.random()*range);
        result += numbers[position];
    }
    return result;    
}

//返回給定寬度的數字字符串
exports.MgetFixedNumber = function(number,width){
    width = width ? width : 2;
    let fixedNumber = number.toString();
    for(; fixedNumber.length < width ; ){
        fixedNumber = "0" + fixedNumber;
    }
    return fixedNumber;
}

//返回 對象屬性排序後的全部鍵和值拼接在在一塊兒的字符串
exports.MgetSortedParameter = function(parameterObject){
    let attributes = [];
    parameterObject = parameterObject ? parameterObject:{};
    for(let attr in parameterObject){
        attributes.push(attr);
    }

    attributes.sort();
    let paramStr = "";
    attributes.forEach(element=>{
        paramStr += element + "=" + parameterObject[element] + "&"
    });

    return paramStr;
}

發送紅包部分

//構造訂單號
function getOrderID(){
    let currentDate = new Date();
    let year = currentDate.getFullYear();
    
    let month = currentDate.getMonth()
    month = month >= 9 ? month + 1 : '0'+(month + 1);
    
    let day = currentDate.getDate()
    day = mutils.MgetFixedNumber(day);
    
    //mch_id 是微信支付分配的商戶號
    let orderid = mch_id + year + month + day + mutils.MgetRandomNumber();

    return orderid;
}

//發紅包
function makeHongBao(openid,res){
    //設置參數模型
    let ParamModel = {};
    ParamModel["nonce_str"] = mutils.MgetRandomStr();//隨機字符串,不長於32位
    ParamModel["wxappid"] = gzh_appid;//公衆帳號appid
    ParamModel["mch_id"] = mch_id;//商戶號 微信支付分配的商戶號 申請中
    ParamModel["mch_billno"] = getOrderID();//商戶訂單號 字母加數字構成 長度最多28位且必須惟一
    ParamModel["send_name"] = "商戶名稱";//商戶名稱 紅包發送者名稱
    ParamModel["re_openid"] = "otWaQ0ztsh9p6X4ZQVMzNa17sTpQ"//公衆號下 用戶openid
    ParamModel["total_amount"] = 100;//付款金額,單位分
    ParamModel["total_num"] = 1;//紅包發放總個數
    ParamModel["wishing"] = "感謝您使用XXX,祝您旗開得勝!";//紅包祝福語 最大長度128位
    ParamModel["client_ip"] = "125.120.226.214";//調用接口的機器Ip地址
    ParamModel["act_name"] = "分享送紅包";//活動名稱
    ParamModel["remark"] = "分享越多送得越多";//備註信息
    ParamModel["scene_id"] = "PRODUCT_5";// 非必須   PRODUCT_6 渠道分潤  紅包金額大於200或者小於1元時必傳 PRODUCT_1
    //ParamModel["notify_way"] ="JSAPI";//通知用戶形式 ------------- 小程序紅包參數?
    //ParamModel["risk_info"] = "posttime%3d123123412%26clientversion%3d234134%26mobile%3d122344545%26deviceid%3dIOS";//活動信息 非必須
    let attrStr = mutils.MgetSortedParameter(ParamModel);
    attrStr += "key=" + mch_key//key爲商戶平臺設置的密鑰key 
    ParamModel["sign"] = mutils.MgetMD5(attrStr);

    //構造POST參數xml
    let contents = '<xml>';
    for( let attr in ParamModel){
        contents += makeXMLNode(attr,ParamModel[attr],false);
    } 
    contents += '</xml>';
    //配置請求選項
    let options = {
        host:'api.mch.weixin.qq.com',
        port:443,
        path:'/mmpaymkttransfers/sendredpack',
        key:fs.readFileSync(__dirname + '/cert/apiclient_key.pem'),
        cert:fs.readFileSync(__dirname + '/cert/apiclient_cert.pem'),
        method:'POST'
    }

    options.agent  =  new https.Agent(options);
    //發送Post請求
    var request = https.request(options, function(response){
        response.setEncoding('utf8');
        response.on('data',function(data){
            console.log("data:",data);
            res.end("wait to do !");
        });
    });

    request.write(contents);
    request.end();
    request.on('error',function(err){
        console.log(err)
    })
}
function makeXMLNode(nodeName,Value,bCTata){
    if (bCTata){
        return '<' + nodeName + '><![CDATA[' + Value + ']]></' + nodeName + '>'
    }

    return '<' + nodeName + '>' + Value + '</' + nodeName + '>'
}

 

如何獲取到公衆號的openid

一、後臺經過公衆號的的appid 和 secret(須要本身設置) 獲取到access_token 官方文檔 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

二、批量獲取到關注公衆號的的用戶信息 注意一次最多獲取一百條  官方文檔 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839

三、把前面提到的unionid 拿來依次和用戶信息裏面的unionid比對 若是相同說明找到正確的用戶了就取它的openid ,就能夠根據這個openid發紅包了

寫得感受有點亂,主要是參考思路,過程比較坑 + 各類掃二維碼 輸驗證碼

node 服務器若是是在外網有固定ip地址,listen函數就不要填ip地址了,否則會報錯

相關文章
相關標籤/搜索