235 lines
7.6 KiB
TypeScript
235 lines
7.6 KiB
TypeScript
import cloud from '@lafjs/cloud'
|
||
const token = "nika123";
|
||
const EncodingAESKey = "XcdOFaZOQjmyBqYHxWAITtrmq11YaZQ63DeEZAAgYJt";
|
||
const mchid = "1719895437";//商户id
|
||
const serialNo = "2A97ED6ED441E55600EBC8830B9EC889ED41496E";//证书序列号
|
||
const appid = "wx30f74367b3d3e7a6";
|
||
import crypto from 'crypto';
|
||
const db = cloud.database();
|
||
export default async function (ctx: FunctionContext) {
|
||
console.log(ctx.body);
|
||
//console.log(ctx.query);;
|
||
try {
|
||
let openid = ctx.body.FromUserName;
|
||
//console.log(openid);
|
||
const data = JSON.parse(ctx.body.SessionFrom);
|
||
//console.log(data);
|
||
console.log(data);
|
||
if (data.tpye == "ios") {
|
||
await PostMsg(openid, "点击下方页面进行充值");
|
||
await PostImg(openid, data.outTradeNo, data.propName, data.count, data.price);
|
||
}
|
||
} catch (e) {
|
||
console.error("ios客服充值参数错误:" + ctx.body.SessionFrom);
|
||
console.log(ctx.body);
|
||
}
|
||
//return ctx.query.echostr;
|
||
return { data: "scuess" };
|
||
}
|
||
/**获取订单*/
|
||
async function getOrder(openid, toatal, outTradeNo, timestamp, nonceStr) {
|
||
const url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
|
||
// 生成随机字符串和时间戳
|
||
const body = {
|
||
"appid": appid,
|
||
"mchid": mchid,
|
||
"description": "消消王者道具购买",
|
||
"out_trade_no": outTradeNo,
|
||
"notify_url": "https://q6rvwvtnga.sealoshzh.site/wx/iosPayCall",
|
||
"amount": { "total": Number(toatal), "currency": "CNY" },
|
||
"payer": { "openid": openid }
|
||
}
|
||
let ret = await sign(nonceStr, timestamp, body);
|
||
const res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Authorization': ret,
|
||
'Accept': 'application/json',
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(body)
|
||
})
|
||
if (res.ok) {
|
||
const data = await res.json().catch(async () => {
|
||
//如果不是JSON,尝试读取文本
|
||
return await res.text().catch(() => 'Empty response');
|
||
});
|
||
return data.prepay_id;
|
||
}
|
||
return null;
|
||
}
|
||
async function sign(nonceStr, timestamp, body) {
|
||
const data = `POST\n/v3/pay/transactions/jsapi\n${timestamp}\n${nonceStr}\n${JSON.stringify(body)}\n`;
|
||
// 创建签名对象
|
||
const sign = crypto.createSign('RSA-SHA256');
|
||
// 更新签名内容
|
||
sign.update(data);
|
||
// 获取存储桶
|
||
const bucket = cloud.storage.bucket('j3k323ol-colorblock-oss');
|
||
// 获取文件列表
|
||
const res = await bucket.readFile('apiclient_key.pem');
|
||
const privateKeyPem = await res.Body.transformToString();
|
||
// 使用私钥签名(PKCS1 填充)
|
||
const signature = sign.sign({
|
||
key: privateKeyPem,
|
||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||
}, 'base64');
|
||
// 构建Authorization头
|
||
const authorization = `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",serial_no="${serialNo}"`;
|
||
return authorization;
|
||
}
|
||
/**前端签名*/
|
||
async function frontsign(data) {
|
||
// 创建签名对象
|
||
const sign = crypto.createSign('RSA-SHA256');
|
||
// 更新签名内容
|
||
sign.update(data);
|
||
// 获取存储桶
|
||
const bucket = cloud.storage.bucket('j3k323ol-colorblock-oss');
|
||
// 获取文件列表
|
||
const res = await bucket.readFile('apiclient_key.pem');
|
||
const privateKeyPem = await res.Body.transformToString();
|
||
//console.error(privateKeyPem);
|
||
// 使用私钥签名(PKCS1 填充)
|
||
const signature = sign.sign({
|
||
key: privateKeyPem,
|
||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||
}, 'base64');
|
||
// 构建Authorization头
|
||
return signature
|
||
}
|
||
const propName = {
|
||
gold_1: "金币包1",
|
||
gold_2: "金币包2",
|
||
gold_3: "金币包3",
|
||
gold_4: "金币包4",
|
||
gold_5: "金币包5",
|
||
gold_6: "金币包6",
|
||
unlimited_health_bundle_1: "无限体力组合包1",
|
||
unlimited_health_bundle_2: "无限体力组合包2",
|
||
unlimited_health_bundle_3: "无限体力组合包3",
|
||
freeze_in_game: "局内购买冻结",
|
||
hammer_in_game: "局内购买锤子",
|
||
wand_in_gamerefill: "局内购买魔棒",
|
||
health: "补满体力"
|
||
};
|
||
|
||
async function PostMsg(OpenId, msg) {
|
||
let token = cloud.shared.get('wxaccess_token');
|
||
if (!token) {
|
||
return { code: 0, data: null, msg: "token获取失败" };
|
||
}
|
||
const url = `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`;
|
||
const data = {
|
||
"touser": OpenId,
|
||
"msgtype": "text",
|
||
"text":
|
||
{
|
||
"content": msg
|
||
}
|
||
}
|
||
|
||
const res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=utf-8'
|
||
},
|
||
body: JSON.stringify(data)
|
||
})
|
||
return "ok"
|
||
}
|
||
async function PostImg(OpenId, outTradeNo, name, count, price) {
|
||
let token = cloud.shared.get('wxaccess_token');
|
||
if (!token) {
|
||
return { code: 0, data: null, msg: "token获取失败" };
|
||
}
|
||
const url = `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token}`;
|
||
const nonceStr = crypto.randomBytes(16).toString('hex');
|
||
const timestamp = Math.floor(Date.now() / 1000).toString();
|
||
const total = count * price;
|
||
let prepay_id = await getOrder(OpenId, total, outTradeNo, timestamp, nonceStr);
|
||
let frontBody = {
|
||
"appId": appid, //公众号ID,由商户传入
|
||
"timeStamp": timestamp, //时间戳,自1970年以来的秒数
|
||
"nonceStr": nonceStr, //随机串
|
||
"package": "prepay_id=" + prepay_id
|
||
}
|
||
const data1 = `${frontBody.appId}\n${frontBody.timeStamp}\n${frontBody.nonceStr}\n${frontBody.package}\n`;
|
||
let paySign = await frontsign(data1);
|
||
|
||
let user = await db.collection("users").where({ openid: OpenId }).update({ iosTime: frontBody.timeStamp });
|
||
let param = {
|
||
name: propName[name],
|
||
openid: OpenId,
|
||
outTradeNo: outTradeNo,
|
||
time: timestamp,
|
||
quantity: count,
|
||
price: price,
|
||
body: {
|
||
"appId": frontBody.appId, //公众号ID,由商户传入
|
||
"timeStamp": frontBody.timeStamp, //时间戳,自1970年以来的秒数
|
||
"nonceStr": frontBody.nonceStr, //随机串
|
||
"package": frontBody.package,
|
||
"signType": "RSA", //微信签名方式:
|
||
"paySign": paySign //微信签名
|
||
}
|
||
}
|
||
await db.collection("iosOrder").add({
|
||
openid: OpenId,
|
||
outTradeNo: outTradeNo,
|
||
itemid: name,
|
||
itemCount: count,
|
||
goodsPrice: Number(price),
|
||
time: Date.now(),
|
||
orderTime: new Date(Date.now() + 8 * 3600000),
|
||
chargeTime: 0,
|
||
getTime: 0,
|
||
type: "ios",
|
||
state: 0,
|
||
});
|
||
const data = {
|
||
"touser": OpenId,
|
||
"msgtype": "link",
|
||
"link": {
|
||
"title": "点我支付",
|
||
"description": "金额:" + (total / 100).toFixed(2) + "元",
|
||
"url": `https://pay.nika4games.com/order3.html#data=${encodeURIComponent(JSON.stringify(param))}`,
|
||
"thumb_url": "https://static-host-j3k323ol-colorblock-oss.sealoshzh.site/icon.jpg"
|
||
}
|
||
}
|
||
//console.log(data);
|
||
const res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=utf-8'
|
||
},
|
||
body: JSON.stringify(data)
|
||
})
|
||
const data11 = await res.json();
|
||
console.log(data11);
|
||
if (data11.errcode == 40001) {
|
||
console.error("未获取到正确token,重新发送请求");
|
||
let res = await getWxToken();
|
||
await PostMsg(OpenId, "点击下方页面进行充值");
|
||
await PostImg(OpenId, outTradeNo, name, count, price);
|
||
}
|
||
return "ok"
|
||
}
|
||
|
||
|
||
/**获取微信Token*/
|
||
async function getWxToken() {
|
||
const api_url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${appsecret}`;
|
||
const ret = await cloud.fetch({
|
||
url: api_url,
|
||
method: "get",
|
||
});
|
||
if (ret?.data?.access_token) {
|
||
cloud.shared.set('wxaccess_token', ret.data.access_token);
|
||
return ret.data.access_token;
|
||
} else {
|
||
//access_token = nul l;
|
||
return null;
|
||
}
|
||
}
|