nodejs -- 从零开始对接微信支付(一无所有,只有执业执照开始)

无营业执照, 其实也可以实现,就是比较麻烦,走的是黑科技路线, 参考payjs, 这个只要付三百块钱就可以, 不需要自己去折腾, 灰产请绕道。

nodejs纯原生例子, 可以直接copy使用,没有框架包袱。
nodejs微信支付最佳实践
nodejs微信支付源码
nodejs微信支付代码、例子
因为我支付宝也是用的黑科技, 所以无法透露, 我们讲讲如何nodejs如何实现微信支付, 从申请支付开始(无公众号等)。

1: 微信支付申请

这一步是免费的。

https://pay.weixin.qq.com 点击进入如下页面

点击成为商家
进入如下链接
https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal
然后扫码申请就可以了。
注意1, 如果是个体户然后经营线上商城是没有对应栏目的, 随便选一个.6栏目的就可以。(为什么不选择更低的?, 因为被查到了很麻烦哦, 其他的好说)
注意2: 遇到问题别用微信客服, 因为你等一辈子他们还是再正在派对中。(我挂了两天, 还在接入, 哦, 提示语一直时还有十个人排队)

申请成功后微信是没有指导你怎么怎么搞得, 我看对接文档说需要上面需要公众号id, 所以我们需要一个公众号。

2: 注册公众号

https://mp.weixin.qq.com 进入公众号注册, 服务号和订阅号都可以, 我推荐用服务号, 权限多, 并且不会被收纳起来(用户寻找入口难)。
然后根据提示操作, 看运气多久审核完成

3: 复制appid跟申请appSecret

开发者中心->配置项

4:申请微信商户平台API密钥、平台证书

传送门 https://pay.weixin.qq.com/index.php/core/cert/api_cert
平台证书就是p12

5, 利用现成的轮子对接支付

tip: 顺便复制下商户号

npm install weixin-pay

去新建pay得公共文件导出这几个对象

var wxpayInfo = {
    appid: 'wx**打码**8',
    mch_id: '1**打码**1',
}
var wxMp = {
    appid: 'wx**打码**8',
    appSecret: '4567**打码**8',
}
var wxpay = WXPay({
    ...wxpayInfo,
    partner_key: 'uiiwx**打码**8', //微信商户平台API密钥
    pfx: fs.readFileSync('./wx/**打码**.p12'), //微信商户平台证书
})

假设配置得叫Config。

公众号支付

Config.wxpay.getBrandWCPayRequestParams({
        openid,
        body,
        detail,
        out_trade_no,
        // 微信金额是以分做单位
        total_fee: amount * 100,
        spbill_create_ip,
        notify_url: 'http://**打码**'
    },  async (err, result) => {
        // CODE  
                // **打码**
    })

但是我们发现 还有参数没有, 对就是openid, 公众号是不支持扫码, 包括二维码图片展示都不可以,你都无法长按扫码(为了增加真实性,我做了亲测, 微信屏蔽了网页得微信协议, 也就是你无法使用原生支付[原生支付跟扫码可以跳过openid])
扫码支付

wxpay.createUnifiedOrder({
    body: '扫码支付测试',
    out_trade_no: '20140703'+Math.random().toString().substr(2, 10),
    total_fee: 1,
    spbill_create_ip: '192.168.2.210',
    notify_url: 'http://wxpay_notify_url',
    trade_type: 'NATIVE',
    product_id: '1234567890'
}, function(err, result){
    console.log(result);
})

但是我们肯定要做微信网页支付,所以,公众号支付是必须的。

6: 获取CODE

先附上微信官方链接,理解能力好的不需要看下面的了
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
1: 先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。(不需要写http、https协议)
注意: OAuth2.0鉴权的域名需要精确到具体路径. # 也算,别以为hash模式就万事大吉。
2: 获取code
在页面进行转跳。
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base &state=STATE#wechat_redirect

把redirect_uri跟appid改下就可以。如果需要xxxxx, 用户信息(会弹出一个用户确定窗口),把scope改成snsapi_userinfo

参考下我的代码

// 微信环境,未授权的进入静默授权,并记录openid到数据库 (支付必须使用openid, 微信里面的网页被微信封了二维码和原生支付)
;(async () => {
  // 用户是否授权了微信
  let wxOpenidInfo = await Config.wxOpenidGet()
  // 分隔符,判断回调
  ,state = 'gou_weixin_return_code__' + Config.wxBase.appid
  // 获取code url
  ,getCodeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${Config.wxBase.appid}&redirect_uri=${Config.wxBase.redirect_uri |> encodeURI}&response_type=code&scope=snsapi_base&state=${state}#wechat_redirect`
  // 获取到的code
  ,codeParams = 'code' |> Config.getUrlParams
  // 获取openid结果
  ,openidResult

  // --------------return 已授权的用户
  if(wxOpenidInfo)
    return
  //------------- 未授权, 未收到code
  if(location.href.indexOf(state) < 0){
    // 去获取code
    location.href = getCodeUrl
    return
  }
  // -----------未授权, 已收到code
  openidResult = await Http.user['wxGetOpenid']({code: codeParams})()
  // 换取openid失败
  if(openidResult.code !== 0){
    openidResult.code === 1 && xxy.toast(openidResult.msg)
    return
  }
  // 换取成功, 储存到openid本地一份, 此时完成后就是已授权了
  openidResult.msg |> Config.wxSaveOpenid
}) |> Config.isWx

上面有xxy(这里用到了弹窗, 你改成你的), HTTP, 改成你的请求,Config,几个基本配置改成你自己的。
附上两个函数代码,判断是否在微信端跟是否授权

  isWx(cb, err){
        // 微信环境
        if(ua.match(/MicroMessenger/i) == 'micromessenger'){
            cb && cb() 
        }else{
            err && err()
        }
    }
    // 用户是否授权了微信
    wxOpenidGet(){
        return new Promise((resolve) => {
            if(localStorage.openid && localStorage.openid.length > 5){
                resolve(true)
                return
            }
            resolve(false)
        })
    }

7: 换取openid

废话少说, 直接上代码, 全是原生实现, 直接copy就可以使用
var https = require('https')
exports.wxGetOpenid = (params) => new Promise(async (resolve, reject) => {
    let {code} = params
    var url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${Config.wxMp.appid}&secret=${Config.wxMp.appSecret}&code=${code}&grant_type=authorization_code`
    https.get(url, (res) => {
        var datas = ''
        res.on('data', (d) => {
            datas += d
        })
        res.on('end', (d) => {
            var result = JSON.parse(datas)
            if(result.errcode){
                resolve({code: 1, msg: result.errmsg})
                return
            }
            if(result.openid){
                resolve({code: 0, msg: result.openid})
                return
            }
        })
    })
    .on('error', (e) => {
      resolve({code: 0, msg: '服务器异常'})
          // ** 打码 **
    })
})

8: 对接回调处理, 退款处理

拿到openid后完成支付功能, 在第5步完成

回调

var util = require('weixin-pay/lib/util.js')
    var xml = Object.keys(body)[0]
    util.parseXML(xml, async (err, msg) => {
        var pkg = JSON.parse(JSON.stringify(msg))
        let sign = msg.sign
        delete pkg.sign
        if (sign !== Config.wxpay.sign(pkg)) {
            // 签名失败,请求不是来自于微信服务器。
                        // **打码**
            return
        }
                // CODE
})

退款

var params = {
    ...Config.wxpayInfo,
    op_user_id: Config.wxpayInfo.mch_id,
    out_refund_no: '20140703'+Math.random().toString().substr(2, 10),
    total_fee: '1', //原支付金额  (以分为单位)
    refund_fee: '1', //退款金额
    transaction_id: '微信订单号'
};

wxpay.refund(params, function(err, result){
    console.log('refund', arguments);
});

OK

参考链接:
https://github.com/tvrcgo/weixin-pay
http://mysy.vip
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

--END--

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容