Commit 4599efd9 by xuzhenzhao

feat(custom): feat: support combination payment

parent c8c1fdcf
...@@ -36,10 +36,7 @@ beforeAll(async () => { ...@@ -36,10 +36,7 @@ beforeAll(async () => {
*/ */
Utils.setCookie(UID, '130960056') Utils.setCookie(UID, '130960056')
Utils.setCookie(ACCESS_TOKEN, 'eccf89e37fb96ef67c4c2cfbe53a05ceMjIwNw') Utils.setCookie(ACCESS_TOKEN, 'eccf89e37fb96ef67c4c2cfbe53a05ceMjIwNw')
globalDatabase.payment = new Payment({ globalDatabase.payment = new Payment({supportCombination: true})
wx_appId: "wx2bc3e1648beb8caa",
zfb_appId: "2021002115687047"
})
}) })
......
...@@ -2,6 +2,21 @@ import {describe, expect, test} from '@jest/globals' ...@@ -2,6 +2,21 @@ import {describe, expect, test} from '@jest/globals'
import {BACK_ORDER_ID, BACK_PAY_ID, PayChannel, PayError, PayErrorMessage, Payment, PayType} from "@/Payment/Payment"; import {BACK_ORDER_ID, BACK_PAY_ID, PayChannel, PayError, PayErrorMessage, Payment, PayType} from "@/Payment/Payment";
describe('测试: 创建实例', () => { describe('测试: 创建实例', () => {
test('supportCombination', () => {
const payment1 = new Payment({
supportCombination: false
})
expect(payment1.supportCombination).toBe(false)
const payment2 = new Payment({
supportCombination: true
})
expect(payment2.supportCombination).toBe(true)
const payment3 = new Payment()
expect(payment3.supportCombination).toBe(true)
})
test('payChannels', () => { test('payChannels', () => {
const payment = new Payment({ const payment = new Payment({
payChannels: [PayChannel.WX_MWEB, PayChannel.WX_JSAPI] payChannels: [PayChannel.WX_MWEB, PayChannel.WX_JSAPI]
...@@ -33,12 +48,21 @@ test('测试订单查询链接', () => { ...@@ -33,12 +48,21 @@ test('测试订单查询链接', () => {
expect(backUrl).toContain(window.location.origin) expect(backUrl).toContain(window.location.origin)
}) })
test('测试价格计算', () => { test('测试组合支付价格计算', () => {
const payment = new Payment(); const payment = new Payment()
const goodsPrice = 0.01; const goodsPrice = 0.3
const payType = PayType.WECHAT; const balance = 0.1
const {payAmount, payBalance} = payment.computeAmount(goodsPrice, payType) const {payAmount, payBalance} = payment.computeAmount(goodsPrice, balance)
expect(payAmount).toBe(0.01) expect(payAmount).toBe(0.2)
expect(payBalance).toBe(0.1)
})
test('测试非组合支付价格计算', () => {
const payment = new Payment({supportCombination: false})
const goodsPrice = 0.3
payment.balance = 0.1
const {payAmount, payBalance} = payment.computeAmount(goodsPrice)
expect(payAmount).toBe(0.3)
expect(payBalance).toBe(0) expect(payBalance).toBe(0)
}) })
......
...@@ -16,7 +16,8 @@ export type BackInfo = { ...@@ -16,7 +16,8 @@ export type BackInfo = {
export type OrderStateCallBack = (params: BackInfo & { isPay: boolean }) => void export type OrderStateCallBack = (params: BackInfo & { isPay: boolean }) => void
export type PaymentParams = { export type PaymentParams = {
payChannels?: PayChannel[] payChannels?: PayChannel[],
supportCombination?: boolean
} }
export enum PayType { export enum PayType {
...@@ -113,14 +114,12 @@ export enum PayErrorMessage { ...@@ -113,14 +114,12 @@ export enum PayErrorMessage {
WECHAT_REDIRECT_URL_MISSING= `请填写微信回调地址页面 'redirectUrl`, WECHAT_REDIRECT_URL_MISSING= `请填写微信回调地址页面 'redirectUrl`,
WECHAT_REDIRECT_URL_ENCODE = 'redirectUrl需要encode', WECHAT_REDIRECT_URL_ENCODE = 'redirectUrl需要encode',
WECHAT_PAY_CHANNEL_MISSING =`缺少渠道参数:'WX_MWEB','WX_JSAPI'`, WECHAT_PAY_CHANNEL_MISSING =`缺少渠道参数:'WX_MWEB','WX_JSAPI'`,
WECHAT_APPID_MISSING = '缺少微信APPID入参',
ALIPAY_QUIT_URL_MISSING = `缺少支付失败回调地址:'quitUrl'`, ALIPAY_QUIT_URL_MISSING = `缺少支付失败回调地址:'quitUrl'`,
ALIPAY_RETURN_URL_MISSING = `缺少支付成功回调地址:'returnUrl'`, ALIPAY_RETURN_URL_MISSING = `缺少支付成功回调地址:'returnUrl'`,
ALIPAY_PAY_CHANNEL_MISSING = `缺少持的渠道参数:'ALI_WAP'`, ALIPAY_PAY_CHANNEL_MISSING = `缺少持的渠道参数:'ALI_WAP'`,
WECHAT_JSSDK_PAY_ERROR = '微信JSSDK支付失败', WECHAT_JSSDK_PAY_ERROR = '微信JSSDK支付失败',
WECHAT_H5_PAY_BREAK = '微信h5支付中断', WECHAT_H5_PAY_BREAK = '微信h5支付中断',
ALIPAY_H5_PAY_BREAK = '支付宝支付中断', ALIPAY_H5_PAY_BREAK = '支付宝支付中断',
ALIPAY_APPID_MISSING = '缺少微信APPID入参',
} }
export type ToPayReturns = { export type ToPayReturns = {
......
...@@ -82,12 +82,15 @@ const requestForJava = defaultRequest ...@@ -82,12 +82,15 @@ const requestForJava = defaultRequest
export class Payment { export class Payment {
balance = 0; balance = 0;
limitPayChannels: PayChannel[] = []; limitPayChannels: PayChannel[] = [];
supportCombination: boolean = true
constructor(paymentParams?: PaymentParams) { constructor(paymentParams?: PaymentParams) {
this.limitPayChannels = paymentParams?.payChannels ?? Object.keys(PayChannel).map(key => key) as PayChannel[]; this.limitPayChannels = paymentParams?.payChannels ?? Object.keys(PayChannel).map(key => key) as PayChannel[];
if (typeof paymentParams?.supportCombination === 'boolean') {
this.supportCombination = typeof paymentParams?.supportCombination === 'boolean' && paymentParams.supportCombination
}
} }
public async getBalance(): Promise<number> { async getBalance(): Promise<number> {
try { try {
const {data: res} = await requestForPhp.post(MY_BALANCE, {balance: 1}) const {data: res} = await requestForPhp.post(MY_BALANCE, {balance: 1})
if (res.data && res.data.balance) { if (res.data && res.data.balance) {
...@@ -98,8 +101,11 @@ export class Payment { ...@@ -98,8 +101,11 @@ export class Payment {
return 0 return 0
} }
} }
getPayMethodList (totalAmount:number) {
return this.supportCombination ? this.getPayMethodListForCombination(totalAmount) : this.getPayMethodListForNotCombination(totalAmount)
}
public getPayMethodList(totalAmount: number): PayMethod[] { private getPayMethodListForNotCombination(totalAmount: number): PayMethod[] {
return FULL_PAY_METHODS.filter(({value}) => { return FULL_PAY_METHODS.filter(({value}) => {
switch (value) { switch (value) {
case PayType.BALANCE: case PayType.BALANCE:
...@@ -123,16 +129,47 @@ export class Payment { ...@@ -123,16 +129,47 @@ export class Payment {
return item return item
}) })
} }
private getPayMethodListForCombination(totalAmount: number): PayMethod[] {
return FULL_PAY_METHODS.filter(({value}) => {
switch (value) {
case PayType.BALANCE:
return this.balance > 0
case PayType.WECHAT:
return this.balance === 0 && !Utils.isAlipay()
case PayType.WECHAT_BALANCE:
return this.balance > 0 && this.balance < totalAmount && !Utils.isAlipay()
case PayType.ALIPAY:
return this.balance === 0 && !Utils.isWechat()
case PayType.ALIPAY_BALANCE:
return this.balance > 0 && this.balance < totalAmount && !Utils.isWechat()
case PayType.HUABEI:
return this.balance === 0 && !Utils.isWechat()
case PayType.HUABEI_BALANCE:
return this.balance > 0 && this.balance < totalAmount && !Utils.isWechat()
}
}).map(item => {
const {payBalance} = this.computeAmount(totalAmount, this.balance)
switch (item.value) {
case PayType.BALANCE:
return {
...item,
label: `余额支付(¥${payBalance})`,
disabled: this.balance > 0 && this.balance < totalAmount
}
}
return item
})
}
computeAmount(totalAmount: number, payType: PayType): { payAmount: number, payBalance: number } { computeAmount(totalAmount: number, balance: number = 0): { payAmount: number, payBalance: number } {
let payBalance = 0, payAmount = 0 let payBalance = 0, payAmount = 0
if(payType == PayType.BALANCE){ if (balance === 0) {
payBalance = totalAmount; payAmount = totalAmount
payAmount = 0; } else if (balance > 0 && balance < totalAmount && this.supportCombination) {
} payBalance = balance
else{ payAmount = subtract(bignumber(totalAmount), bignumber(balance)).toNumber()
payBalance = 0; } else {
payAmount = totalAmount; payBalance = totalAmount
} }
return {payAmount, payBalance} return {payAmount, payBalance}
} }
...@@ -209,7 +246,7 @@ export class Payment { ...@@ -209,7 +246,7 @@ export class Payment {
orderId, orderId,
payType, payType,
payId, payId,
...this.computeAmount(totalAmount, payType), ...this.computeAmount(totalAmount, this.balance),
} }
if (payChannel !== null) { if (payChannel !== null) {
doUnifiedParams.payChannel = payChannel doUnifiedParams.payChannel = payChannel
...@@ -217,7 +254,7 @@ export class Payment { ...@@ -217,7 +254,7 @@ export class Payment {
const res = await requestForJava.post<DoUnifiedParams, DefaultResponse>(UNIT_PAY, doUnifiedParams) const res = await requestForJava.post<DoUnifiedParams, DefaultResponse>(UNIT_PAY, doUnifiedParams)
if (res.code !== '200') return {errorMessage: res.msg as any, success: false, errorType: PayError.BACKEND} if (res.code !== '200') return {errorMessage: res.msg as any, success: false, errorType: PayError.BACKEND}
if (params.payType === PayType.BALANCE && res.data) { if (params.payType === PayType.BALANCE && res.data) {
return {success: res.data.result, errorType: PayError.BALANCE} //返回回调地址 return {success: res.data.result, errorType: PayError.BALANCE}
} else if (payChannel === PayChannel.WX_JSAPI) { } else if (payChannel === PayChannel.WX_JSAPI) {
const isPaySucc = await this.wechatPayJSSDK(res.data.content) const isPaySucc = await this.wechatPayJSSDK(res.data.content)
return { return {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment