微信支付
app/小程序支付

企业付款到零钱文档;https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

1、微信支付,先看流程图

https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3

先看流程图,看懂,再看微信支付api

2、调用统一下单接口

Controller

import {Controller} from 'egg';
export default class Wx extends Controller{

    public async wxpay(){
        const ctx = this.ctx;
        const result = await ctx.service.weixin.payunifiedorder();
        ctx.body = result;
    }

    /* 微信回调 */
    public async wxNotify(){
        const ctx = this.ctx;
        const result = await ctx.service.weixin.wxNotify(ctx.params);
        ctx.body = result
    }
}

Service

import { Service } from 'egg';
import * as xmlbuilder from 'xmlbuilder';
import * as uuidv5 from 'uuid/v5';
import * as qs from 'qs';
import * as md5 from 'md5';

const appid:string="appid";
const secret:string="secret"

export default class Weixin extends Service{

    /* 获取微信openid */
    public async getUserOpenid({code}):Promise<object>{
        const ctx = this.ctx;
        const result = await ctx.curl(`https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}=&js_code=${code}&grant_type=authorization_code`,{
            method:"GET"
        });
        return result.data;
    }

    /* 获取微信access_token */
    public async getAccess_token():Promise<object>{
        const ctx = this.ctx;
        const result = await ctx.curl(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`,{
            method:"GET"
        });
        return result.data;
    }

    /* 统一下单 */
    public async payunifiedorder():Promise<object>{
        const ctx = this.ctx;
        let uuid = uuidv5("",uuidv5.DNS).replace(/-/g, '').toUpperCase()
        console.log(ctx.ip.replace(/::ffff:/g, ''))
        let order:any={
            appid,
            body:"腾讯充值中心-QQ会员充值",
            nonce_str:uuid,
            notify_url:"http://x5z5g2.natappfree.cc/getpay",
            out_trade_no:uuid,
            spbill_create_ip:"123.12.12.123",
            total_fee:1,
            trade_type:"APP",
        }
        const objStr = qs.stringify(order)
        const preSign = objStr + '&key=192006250b4c09247ec02edce69f6a2d'
        order.sign = md5(preSign).toUpperCase();
        let xml = xmlbuilder.create(order).end({ pretty: true});
        const result:any = await ctx.curl(`https://api.mch.weixin.qq.com/pay/unifiedorder`,{
            method:'POST',
            data:xml
        });
        console.log(result.data)
        //二次签名,返回给app即可,由app端进行微信支付吊起
        const paysign2:any = {
            appid: result.data.appid[0],
            noncestr: result.data.nonce_str[0],
            package: 'Sign=WXPay',
            partnerid: result.data.mch_id[0],
            prepayid: result.data.prepay_id[0],
            timestamp:Number(Date.now() / 1000) //注意:时间必需为秒
        };

        const payPrestr = qs.stringify(paysign2) + 'key=微信商户平台的key' //不知道的话,可以问老板
        paysign2.sign = md5(payPrestr).toUpperCase()
        return paysign2;
    }

    // 微信回调
    public async wxNotify(params){
        const ctx = this.ctx;
        // 接受微信参数
        var payQuery:any = {
            appid: params.appid[0],
            mch_id: params.mch_id[0],
            nonce_str: params.nonce_str[0],
            out_trade_no: params.out_trade_no[0],
            transaction_id: params.transaction_id[0]
        }
        let payQueryString = qs.stringify(payQuery) + 'key=微信商户平台的key'
        payQuery.sign = md5(payQueryString).toUpperCase()
        let payQueryxml = xmlbuilder.create(payQuery).end({ pretty: true});
        //查询订单是否支付成功
        const result:any = await ctx.curl(`https://api.mch.weixin.qq.com/pay/orderquery`,{
            method:'POST',
            data:payQueryxml
        });

         if (result.data.xml.return_code[0] && result.xml.return_code[0] == 'SUCCESS' && result.xml.trade_state[0] == 'SUCCESS' ) {
                //告诉微信,你收到支付结果通知了
            let res = {
                return_code:"<![CDATA[SUCCESS]]>",
                return_msg:"<![CDATA[OK]]>"
            }
            let resxml = xmlbuilder.create(res).end({ pretty: true});
            return resxml;
        }
    }
}