ClojureScript Repl开发微信小程序库体验, 爽呆了!!! => 成为开发者,请点击文字
- wechat-clj微信开发全家桶: 微信支付,小程序库,服务号开发,代码生成器等
- Features
- Usage
- 微信小程序
- 微信服务号
- 基础支持-获取access_token: 定时器获取
- 基础支持-获取微信服务器IP地址
- 接收消息-验证消息真实性、接收普通消息、接收事件推送、接收语音识别结果
- 发送消息-被动回复消息
- 发送消息-客服接口
- 发送消息-群发接口
- 发送消息-模板消息接口
- 发送消息-一次性订阅消息接口
- 用户管理-用户分组管理
- 用户管理-设置用户备注名
- 用户管理-获取用户基本信息
- 用户管理-获取用户列表
- 用户管理-获取用户地理位置
- 用户管理-网页授权获取用户openid/用户基本信息: oauth2服务号的二次授权
- 推广支持-生成带参数二维码
- 推广支持-长链接转短链接口
- 界面丰富-自定义菜单
- 素材管理-素材管理接口
- 智能接口-语义理解接口
- 多客服-获取多客服消息记录、客服管理
- 微信支付接口
- 微信小店接口
- 微信卡券接口
- 微信设备功能接口
- 微信发票接口
- 微信JS-SDK-基础接口: 微信服务号jsapi签名
wx.config
(用于微信网页支付和分享等的初始化) - 微信JS-SDK-分享接口
- 微信JS-SDK-图像接口
- 微信JS-SDK-音频接口
- 微信JS-SDK-智能接口
- 微信JS-SDK-设备信息
- 微信JS-SDK-地理位置
- 微信JS-SDK-界面操作
- 微信JS-SDK-微信扫一扫
- 微信JS-SDK-微信小店
- 微信JS-SDK-微信卡券
- 微信JS-SDK-微信支付
- 成为开发者
- License
- 微信支付的后端相关加密,包含小程序和微信服务号
- 微信服务号的二次授权
- 小程序的jscode2session和登录
- 微信服务号获取用户信息的接口map
- shadow-cljs 编写小程序的需要的npm库mini-program-cljs
- 微信小程序的支付
- 微信服务号的支付
- 微信小程序的UI组件库
- Hiccup生成微信小程序的前端页面: Elisp混合clomacs生成方案 和 纯Clojure生成wxml和wxss代码方案
- 微信客户机器人和开发
- 签名,加解密和验证成功与否的工具函数或者spec解释器: spec出来具体很细的签名哪一部分错了,前端还是后端,还是排序还是大小写,缺了哪个字段等,大大减少验证签名的时间
- 给每一个调用的前后端函数写Spec,严格化工程
- 基于miniprogram-automator完善ClojureScript和Shadow开发微信小程序库的流程和自动化工具,测试链(Repl式的开发体验)
- 基于小程序的canvas画图类库: 可以快速写出"头像加国旗"类的小程序来
- Clojure(Script)前后端库wechat-clj
[wechat-clj "0.2.3"]
- 微信小程序的cljs库mini-program-cljs: 安装
mini-program-cljs
npm i mini-program-cljs
## Mac的微信开发者工具再编译:
/Applications/wechatwebdevtools.app/Contents/MacOS/cli --build-npm ~/YourWechatProject
import { MiniCljs } from 'mini-program-cljs';
MiniCljs.alert("Hello, mini-program-cljs!");
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取用户信息登陆</button>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"> 获取用户手机登陆</button>
Page({
getUserInfo: function(e) {
MiniCljs.login({successFn: function(res) {
encrypted_data: res.encryptedData,
iv: res.iv,
jscode: res.code}})
},
getPhoneNumber: function(e) {
MiniCljs.login({successFn: function(res) {
encrypted_data: res.encryptedData,
iv: res.iv,
jscode: res.code}})
}
})
//=> res: 将res的内容传递给后端的接口即可获取用户的信息(openid等)
{code: "043Ndldz0WVpcc1Cqpcz03Xgdz0...."
encryptedData: "NxmCRAyhhMT2jzdcu012VJznC6HH0H....."
iv: "jbjTusiIz2tfzt1ddU..=="}
- 后端的jscode2session的API
(ns your.ns
(:require [wechat-clj.jscode2session :refer [get-jscode2session decrypt-wxdata]]))
(defn jscode2session-api [{{:keys [jscode encrypted_data iv]} :params}]
(let [{:keys [appid secret]} {:appid "小程序的appid" :secret "小程序的secret"}
{:keys [errcode errmsg hints session_key expires_in openid unionid]}
(get-jscode2session {:jscode jscode :wxapp-key wxapp-key :op-fn #(identity %)})]
(let [wx-user-data
(decrypt-wxdata {:encrypted_data encrypted_data
:session_key session_key
:iv iv})]
;; 加入表存储你需要的微信用户信息
wx-user-data
;;
)))
MiniCljs.request(
{url: 'https://www.test.com/login/jscode2session',
method: "GET",
data: {encrypted_data: res.encryptedData,
iv: res.iv,
jscode: res.code}}).then(res => {
console.log("登陆返回数据");
console.log(res);
if(res.statusCode == 200){
// ...
} else {
// ...
}
}).catch(err => {
MiniCljs.alert(err.message)
})
;; TODO
;; TODO
;; TODO
MiniCljs.testFun(this, arg1 ...)
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
- 后端API同服务号的微信支付的用法
- 前端小程序
// TODO: 需要封装
wx.requestPayment({
'timeStamp': res.data.timeStamp,
'nonceStr': res.data.nonceStr,
'package': "prepay_id=" + res.data.prepayId,
'signType': 'MD5',
'paySign': res.data.paySign,
'success':function(res){
console.log(res);
MiniCljs.alert("支付成功");
},
'fail':function(res){
console.log(res);
MiniCljs.alert("支付失败");
},
'complete':function(res){
console.log(res);
MiniCljs.alert("支付完成");
}
})
(ns your.ns
(:require [wechat-clj.public.core]))
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
(ns your.ns
(:require [wechat-clj.oauth2]))
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
- 后端接口获取或模板嵌入html携带jsapi的签名信息
(ns your.ns
(:require [wechat-clj.wxpay.public :as wx-public]))
(defn url-signature [url]
(wx-public/url-signature
{:appid {:appid "服务号的appid" :secret "服务号的secret"}
:url url
:debug true
:official-account-jsapi-ticket "服务号的jsapi ticket: 详情见wechat-clj.public.core的文档"}))
(defn get-wx-jsapi-signature [request]
(let [request-url (str
"http://your.domain"
(:uri request)
(wx-public/hash-params->url
(:params req)))]
{:signature (-> request-url
url-signature
json/generate-string)}))
- 前端cljs获取后端的签名
signature
(ns your.ns
(:require [wechat-clj.core :refer [wx-jsapi-init]]))
(wx-jsapi-init signature)
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
;; TODO
- 后端支付的接口的用法(假设用MD5签名)
(ns your.ns
(:require [wechat-clj.wxpay.api :as wxpay]))
;; 读取微信支付的cert证书
(def wxpay-cert-byte
(future
(wxpay/read-wxpay-cert-byte "apiclient_cert.p12")))
(let [res (wxpay/unified-order
wxpay-confg
{:body "测试支付"
:total_fee 1
:trade_type "JSAPI"
:openid "你的微信openid"
:out-trade-no "321320989890312(交易id)"
:op-fn identity
:cert @wxpay-cert-byte
:callback-url "https://支付成功回调的api接口"})
;;res正确返回的样子 => {:msg "ok", :res {"nonce_str" "6So2RRrVGKuBSxxxx", "code_url" "weixin://wxpay/bizpayurl?pr=2KEuxxx", "appid" "wxcxxxxx1121", "sign" "B4ACAE399E2307252xxxxx11", "trade_type" "JSAPI", "return_msg" "OK", "result_code" "SUCCESS", "mch_id" "13125434531", "return_code" "SUCCESS", "prepay_id" "wx022007560531243142423317900"}, :out_trade_no "aasdas321312asdds3123"}
time-stamp (str (wxpay/get-unix-second))]
;; 注意: 微信之后的签名下单,默认为MD5签名 # 前端wx.chooseWXPay方法也会验证一次后端的签名是否一致
(let [signature
(wxpay/signature
{:appid "服务号appid" :key "微信支付的key"}
{:nonceStr (get (:res res) "nonce_str")
:prepay_id (get (:res res) "prepay_id")
:timeStamp time-stamp})]
;; 最后API返回给前端wx.chooseWXPay支付需要的信息
{:timeStamp time-stamp
:nonceStr nonce_str
:prepayId prepay_id
:paySign signature}
)
)
- 微信支付成功的回调XML解析,更新微信支付的状态机
(ns your.ns
(:require [wechat-clj.util :as wechat-u]))
(defn your-wxpay-callback
[request]
(let [req-xml-body (slurp (:body request))
{:keys [out_trade_no return_code] :as params} (wechat-u/parse-wxpay-callback-xml req-xml-body)]
;; 在数据库中将订单号的对应的状态设置为支付成功
;; ===>>> req-xml-body 样例
;;<xml><appid><![CDATA[wx321sde321]]></appid>
;;<bank_type><![CDATA[GDB_CREDIT]]></bank_type>
;;<cash_fee><![CDATA[1]]></cash_fee>
;;<fee_type><![CDATA[CNY]]></fee_type>
;;<is_subscribe><![CDATA[Y]]></is_subscribe>
;;<mch_id><![CDATA[15das321321]]></mch_id>
;;<nonce_str><![CDATA[bd650baa321321a2d02c5e]]></nonce_str>
;;<openid><![CDATA[o3Nbh0j0dasdas321321Z_x8Tq8s]]></openid>
;;<out_trade_no><![CDATA[135b652e27321321das5393b2d910a3cc]]></out_trade_no>
;;<result_code><![CDATA[SUCCESS]]></result_code>
;;<return_code><![CDATA[SUCCESS]]></return_code>
;;<sign><![CDATA[4E973EAA376203213210dasdas20035C]]></sign>
;;<time_end><![CDATA[201912263213249]]></time_end>
;;<total_fee>1</total_fee>
;;<trade_type><![CDATA[JSAPI]]></trade_type>
;;<transaction_id><![CDATA[4200000321321d32132105020]]></transaction_id>
;;</xml>
))
- 前端支付调用的用法(假设用MD5签名)
(ns your.ns
(:require [wechat-clj.wxpay :as wxpay]))
;; 下面的四个参数都是后端传过来的
(wxpay/choose-wxpay
{:time-stamp time-stamp
:nonce-str nonce-str
:prepay-id prepay-id
:pay-sign pay-sign})
基于miniprogram-automator开发ClojureScript小程序库
;; TODO
;; TODO
Copyright © 2020 Steve Chan