@social-mail/social-mail-web-server 1.4.847 → 1.4.849
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/seed/ui/seed-ui.js +1 -1
- package/dist/server/services/payment-gateways/Gateway.d.ts +13 -3
- package/dist/server/services/payment-gateways/Gateway.d.ts.map +1 -1
- package/dist/server/services/payment-gateways/Gateway.js +37 -1
- package/dist/server/services/payment-gateways/Gateway.js.map +1 -1
- package/dist/server/services/payment-gateways/PhonePeGateway.d.ts +2 -4
- package/dist/server/services/payment-gateways/PhonePeGateway.d.ts.map +1 -1
- package/dist/server/services/payment-gateways/PhonePeGateway.js +9 -15
- package/dist/server/services/payment-gateways/PhonePeGateway.js.map +1 -1
- package/dist/server/services/store/StoreConfigService.d.ts +4 -0
- package/dist/server/services/store/StoreConfigService.d.ts.map +1 -1
- package/dist/server/services/store/StoreConfigService.js +32 -0
- package/dist/server/services/store/StoreConfigService.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/wwwroot/routes/pg-i/phone-pe/create/index.d.ts +2 -4
- package/dist/wwwroot/routes/pg-i/phone-pe/create/index.d.ts.map +1 -1
- package/dist/wwwroot/routes/pg-i/phone-pe/create/index.js +6 -74
- package/dist/wwwroot/routes/pg-i/phone-pe/create/index.js.map +1 -1
- package/package.json +1 -1
- package/src/server/seed/ui/seed-ui.ts +1 -1
- package/src/server/services/payment-gateways/Gateway.ts +30 -3
- package/src/server/services/payment-gateways/PhonePeGateway.ts +9 -10
- package/src/server/services/store/StoreConfigService.ts +23 -0
- package/src/wwwroot/routes/pg-i/phone-pe/create/index.tsx +6 -88
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
2
|
-
import
|
|
3
|
-
import StoreConfigService from "../../../../../server/services/store/StoreConfigService.js";
|
|
2
|
+
import PhonePeGateway from "../../../../../server/services/payment-gateways/PhonePeGateway.js";
|
|
4
3
|
export default class extends Page {
|
|
5
|
-
|
|
6
|
-
configService: StoreConfigService;
|
|
4
|
+
gateway: PhonePeGateway;
|
|
7
5
|
run(): Promise<import("@entity-access/server-pages/dist/Content.js").Redirect>;
|
|
8
6
|
}
|
|
9
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/pg-i/phone-pe/create/index.tsx"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/pg-i/phone-pe/create/index.tsx"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,cAAc,MAAM,mEAAmE,CAAC;AAE/F,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,OAAO,EAAE,cAAc,CAAC;IAElB,GAAG;CASZ"}
|
|
@@ -9,85 +9,17 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import Inject from "@entity-access/entity-access/dist/di/di.js";
|
|
11
11
|
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
12
|
-
import
|
|
13
|
-
import StoreConfigService from "../../../../../server/services/store/StoreConfigService.js";
|
|
14
|
-
import { randomUUID } from "crypto";
|
|
15
|
-
import { createHash } from "node:crypto";
|
|
12
|
+
import PhonePeGateway from "../../../../../server/services/payment-gateways/PhonePeGateway.js";
|
|
16
13
|
export default class default_1 extends Page {
|
|
17
14
|
async run() {
|
|
18
|
-
const [
|
|
15
|
+
const [itemID, currency] = this.childPath;
|
|
19
16
|
const host = this.request.hostName;
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
// if (!this.sessionUser.isAdmin) {
|
|
23
|
-
// q = q.where({ host }, (p) => (x) =>
|
|
24
|
-
// x.storeItem.store.storeWebsites.some((w) => w.website.hosts.some((h) => h.host === p.host))
|
|
25
|
-
// );
|
|
26
|
-
// }
|
|
27
|
-
const itemPrice = await q
|
|
28
|
-
.include((x) => [x.storeItem.variantFor, x.storeItem.sizeFor])
|
|
29
|
-
.firstOrFail();
|
|
30
|
-
let name = "phone-pe";
|
|
31
|
-
if (this.query.test) {
|
|
32
|
-
name = "phone-pe-test";
|
|
33
|
-
}
|
|
34
|
-
const config = await this.configService.getConfigs(itemPrice.storeItem.storeID, name);
|
|
35
|
-
const { merchantId, url, keyIndex, key } = config;
|
|
36
|
-
const merchantTransactionId = randomUUID().replaceAll("-", "");
|
|
37
|
-
const createRequest = {
|
|
38
|
-
merchantId,
|
|
39
|
-
merchantTransactionId,
|
|
40
|
-
merchantUserId: randomUUID().replaceAll("-", ""),
|
|
41
|
-
amount: itemPrice.amount * 100,
|
|
42
|
-
callbackUrl: `https://${host}/callbacks/phonepe-callback/${merchantTransactionId}`,
|
|
43
|
-
redirectUrl: `https://${host}/callbacks/phonepe-success/${merchantTransactionId}`,
|
|
44
|
-
paymentInstrument: {
|
|
45
|
-
type: "PAY_PAGE"
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
const { request, verify } = signRequest(keyIndex, key, JSON.stringify(createRequest));
|
|
49
|
-
const r = await fetch((url.endsWith("/") ? url.substring(1) : url) + "/pg/v1/pay", {
|
|
50
|
-
method: "POST",
|
|
51
|
-
headers: {
|
|
52
|
-
"x-verify": verify,
|
|
53
|
-
"content-type": "application/json"
|
|
54
|
-
},
|
|
55
|
-
body: JSON.stringify({ request })
|
|
56
|
-
});
|
|
57
|
-
if (r.status >= 300) {
|
|
58
|
-
throw new Error(await r.text());
|
|
59
|
-
}
|
|
60
|
-
const text = await r.text();
|
|
61
|
-
try {
|
|
62
|
-
const rs = JSON.parse(text);
|
|
63
|
-
if (rs.success) {
|
|
64
|
-
const redirectUrl = rs?.data?.instrumentResponse?.redirectInfo?.url;
|
|
65
|
-
if (redirectUrl) {
|
|
66
|
-
return this.redirect(redirectUrl);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
throw new Error("Failed");
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
throw new Error(text);
|
|
73
|
-
}
|
|
17
|
+
const pr = await this.gateway.createPaymentLink({ itemID, currency, host, testMode: this.query.test });
|
|
18
|
+
return this.redirect(pr.url);
|
|
74
19
|
}
|
|
75
20
|
}
|
|
76
21
|
__decorate([
|
|
77
22
|
Inject,
|
|
78
|
-
__metadata("design:type",
|
|
79
|
-
], default_1.prototype, "
|
|
80
|
-
__decorate([
|
|
81
|
-
Inject,
|
|
82
|
-
__metadata("design:type", StoreConfigService)
|
|
83
|
-
], default_1.prototype, "configService", void 0);
|
|
84
|
-
function signRequest(id, salt, payload, path = "/pg/v1/pay") {
|
|
85
|
-
const request = Buffer.from(payload, "utf-8").toString("base64");
|
|
86
|
-
const signPayload = `${request}${path}${salt}`;
|
|
87
|
-
const sha256 = createHash("sha256").update(signPayload).digest("hex");
|
|
88
|
-
return {
|
|
89
|
-
request,
|
|
90
|
-
verify: `${sha256}###${id}`
|
|
91
|
-
};
|
|
92
|
-
}
|
|
23
|
+
__metadata("design:type", PhonePeGateway)
|
|
24
|
+
], default_1.prototype, "gateway", void 0);
|
|
93
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/pg-i/phone-pe/create/index.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/pg-i/phone-pe/create/index.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAC5D,OAAO,cAAc,MAAM,mEAAmE,CAAC;AAE/F,MAAM,CAAC,OAAO,gBAAO,SAAQ,IAAI;IAK7B,KAAK,CAAC,GAAG;QAEL,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAE,GAAG,IAAI,CAAC,SAAkB,CAAC;QAEpD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAEnC,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACvG,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;CACJ;AAXG;IADC,MAAM;8BACE,cAAc;0CAAC"}
|
package/package.json
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import Inject from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
3
|
+
import StoreConfigService from "../store/StoreConfigService.js";
|
|
4
|
+
|
|
1
5
|
export interface IPaymentGatewayCreateRequest {
|
|
2
6
|
storeID: number;
|
|
3
7
|
userID: string;
|
|
@@ -19,10 +23,33 @@ export interface IPaymentGatewayGetResponse {
|
|
|
19
23
|
success: boolean;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
export
|
|
26
|
+
export abstract class PaymentGateway {
|
|
27
|
+
|
|
28
|
+
@Inject
|
|
29
|
+
configService: StoreConfigService;
|
|
30
|
+
|
|
31
|
+
@Inject
|
|
32
|
+
db: SocialMailContext;
|
|
33
|
+
|
|
34
|
+
async createPaymentLink({ itemID, host, testMode = false, currency = "USD"}) {
|
|
35
|
+
const { price, taxes } = await this.configService.getPrice(itemID, currency);
|
|
36
|
+
let total = price.amount;
|
|
37
|
+
for (const iterator of taxes) {
|
|
38
|
+
total += (price.amount*iterator.amount);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return this.create({
|
|
42
|
+
storeID: price.storeItem.storeID,
|
|
43
|
+
amount: total,
|
|
44
|
+
orderID: void 0,
|
|
45
|
+
userID: void 0,
|
|
46
|
+
host,
|
|
47
|
+
testMode
|
|
48
|
+
});
|
|
49
|
+
}
|
|
23
50
|
|
|
24
|
-
create(req:IPaymentGatewayCreateRequest): Promise<IPaymentGatewayCreateResponse>;
|
|
51
|
+
abstract create(req:IPaymentGatewayCreateRequest): Promise<IPaymentGatewayCreateResponse>;
|
|
25
52
|
|
|
26
|
-
get(req:IPaymentGatewayGetRequest): Promise<IPaymentGatewayGetResponse>;
|
|
53
|
+
abstract get(req:IPaymentGatewayGetRequest): Promise<IPaymentGatewayGetResponse>;
|
|
27
54
|
|
|
28
55
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Inject, { RegisterScoped } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import {
|
|
2
|
+
import { PaymentGateway, IPaymentGatewayCreateRequest, IPaymentGatewayCreateResponse, IPaymentGatewayGetRequest, IPaymentGatewayGetResponse } from "./Gateway.js";
|
|
3
3
|
import StoreConfigService from "../store/StoreConfigService.js";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
|
|
6
6
|
const signRequest = (id: any, salt: any, payload: string, path = "/pg/v1/pay"): { request: any; verify: any; } => {
|
|
7
7
|
const request = Buffer.from(payload, "utf-8").toString("base64");
|
|
@@ -15,14 +15,13 @@ const signRequest = (id: any, salt: any, payload: string, path = "/pg/v1/pay"):
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@RegisterScoped
|
|
18
|
-
export default class PhonePeGateway
|
|
19
|
-
|
|
20
|
-
@Inject
|
|
21
|
-
configService: StoreConfigService;
|
|
18
|
+
export default class PhonePeGateway extends PaymentGateway {
|
|
22
19
|
|
|
23
20
|
async create({ storeID, testMode, orderID, userID, amount, host }: IPaymentGatewayCreateRequest): Promise<IPaymentGatewayCreateResponse> {
|
|
24
21
|
|
|
25
|
-
const
|
|
22
|
+
const name = testMode ? "phone-pe-test" : "phone-pe";
|
|
23
|
+
|
|
24
|
+
const config = await this.configService.getConfigs(storeID, name);
|
|
26
25
|
|
|
27
26
|
const {
|
|
28
27
|
merchantId,
|
|
@@ -31,12 +30,12 @@ export default class PhonePeGateway implements IPaymentGateway {
|
|
|
31
30
|
key
|
|
32
31
|
} = config;
|
|
33
32
|
|
|
34
|
-
const merchantTransactionId = orderID;
|
|
33
|
+
const merchantTransactionId = orderID ?? randomUUID().replaceAll("-", "");
|
|
35
34
|
|
|
36
35
|
const createRequest = {
|
|
37
36
|
merchantId,
|
|
38
37
|
merchantTransactionId,
|
|
39
|
-
merchantUserId: userID,
|
|
38
|
+
merchantUserId: userID ?? randomUUID().replaceAll("-", ""),
|
|
40
39
|
amount: amount * 100,
|
|
41
40
|
callbackUrl: `https://${host}/callbacks/phonepe-callback/${merchantTransactionId}`,
|
|
42
41
|
redirectUrl: `https://${host}/callbacks/phonepe-success/${merchantTransactionId}`,
|
|
@@ -64,7 +63,7 @@ export default class PhonePeGateway implements IPaymentGateway {
|
|
|
64
63
|
if (rs.success) {
|
|
65
64
|
const redirectUrl = rs?.data?.instrumentResponse?.redirectInfo?.url;
|
|
66
65
|
if (redirectUrl) {
|
|
67
|
-
return
|
|
66
|
+
return redirectUrl;
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
throw new Error("Failed");
|
|
@@ -5,6 +5,7 @@ import SocialMailContext from "../../model/SocialMailContext.js";
|
|
|
5
5
|
import EncryptionService from "../encryption/EncryptionService.js";
|
|
6
6
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
7
7
|
import { chainToCamel } from "../../../common/chainToCamel.js";
|
|
8
|
+
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
8
9
|
|
|
9
10
|
@RegisterSingleton
|
|
10
11
|
export default class StoreConfigService {
|
|
@@ -38,4 +39,26 @@ export default class StoreConfigService {
|
|
|
38
39
|
).first();
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
@cacheFor()
|
|
43
|
+
async getPrice(itemID, currency) {
|
|
44
|
+
using scope = ServiceProvider.createScope(this);
|
|
45
|
+
const db = scope.resolve(SocialMailContext);
|
|
46
|
+
|
|
47
|
+
const now = DateTime.now;
|
|
48
|
+
|
|
49
|
+
const q = db.storeItemPrices.where({ currency, now }, (p) => (x) =>
|
|
50
|
+
x.currency === p.currency
|
|
51
|
+
&& x.startDate as any <= Sql.cast.asDateTime(p.now)
|
|
52
|
+
&& (x.endDate === null || x.endDate as any > p.now)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const price = await q.where({ itemID }, (p) => (x) => x.storeItemID === p.itemID)
|
|
56
|
+
.include((x) => x.storeItem)
|
|
57
|
+
.first();
|
|
58
|
+
|
|
59
|
+
const taxes = await q.where({ itemID} , (p) => (x) => x.storeItem.taxItems.some((ti) => ti.storeItemID === p.itemID))
|
|
60
|
+
.toArray();
|
|
61
|
+
|
|
62
|
+
return { price, taxes };
|
|
63
|
+
}
|
|
41
64
|
}
|
|
@@ -1,102 +1,20 @@
|
|
|
1
1
|
import Inject from "@entity-access/entity-access/dist/di/di.js";
|
|
2
2
|
import Page from "@entity-access/server-pages/dist/Page.js";
|
|
3
|
-
import
|
|
4
|
-
import StoreConfigService from "../../../../../server/services/store/StoreConfigService.js";
|
|
5
|
-
import { randomUUID } from "crypto";
|
|
6
|
-
import { globalEnv } from "../../../../../common/globalEnv.js";
|
|
7
|
-
import { createHash } from "node:crypto";
|
|
3
|
+
import PhonePeGateway from "../../../../../server/services/payment-gateways/PhonePeGateway.js";
|
|
8
4
|
|
|
9
5
|
export default class extends Page {
|
|
10
6
|
|
|
11
7
|
@Inject
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@Inject
|
|
15
|
-
configService: StoreConfigService;
|
|
8
|
+
gateway: PhonePeGateway;
|
|
16
9
|
|
|
17
10
|
async run() {
|
|
18
11
|
|
|
19
|
-
const [
|
|
20
|
-
const host = this.request.hostName;
|
|
21
|
-
|
|
22
|
-
const q = this.db.storeItemPrices
|
|
23
|
-
.where({ itemPriceID, host }, (p) => (x) =>
|
|
24
|
-
x.priceID === p.itemPriceID
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
// if (!this.sessionUser.isAdmin) {
|
|
28
|
-
// q = q.where({ host }, (p) => (x) =>
|
|
29
|
-
// x.storeItem.store.storeWebsites.some((w) => w.website.hosts.some((h) => h.host === p.host))
|
|
30
|
-
// );
|
|
31
|
-
// }
|
|
32
|
-
|
|
33
|
-
const itemPrice = await q
|
|
34
|
-
.include((x) => [x.storeItem.variantFor, x.storeItem.sizeFor])
|
|
35
|
-
.firstOrFail();
|
|
36
|
-
|
|
37
|
-
let name = "phone-pe";
|
|
38
|
-
if (this.query.test) {
|
|
39
|
-
name = "phone-pe-test";
|
|
40
|
-
}
|
|
12
|
+
const [itemID, currency ] = this.childPath as any[];
|
|
41
13
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
const {
|
|
45
|
-
merchantId,
|
|
46
|
-
url,
|
|
47
|
-
keyIndex,
|
|
48
|
-
key
|
|
49
|
-
} = config;
|
|
50
|
-
|
|
51
|
-
const merchantTransactionId = randomUUID().replaceAll("-", "");
|
|
52
|
-
|
|
53
|
-
const createRequest = {
|
|
54
|
-
merchantId,
|
|
55
|
-
merchantTransactionId,
|
|
56
|
-
merchantUserId: randomUUID().replaceAll("-", ""),
|
|
57
|
-
amount: itemPrice.amount * 100,
|
|
58
|
-
callbackUrl: `https://${host}/callbacks/phonepe-callback/${merchantTransactionId}`,
|
|
59
|
-
redirectUrl: `https://${host}/callbacks/phonepe-success/${merchantTransactionId}`,
|
|
60
|
-
paymentInstrument: {
|
|
61
|
-
type: "PAY_PAGE"
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const { request, verify } = signRequest(keyIndex, key, JSON.stringify(createRequest));
|
|
14
|
+
const host = this.request.hostName;
|
|
66
15
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
headers: {
|
|
70
|
-
"x-verify": verify,
|
|
71
|
-
"content-type": "application/json"
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify({ request })
|
|
74
|
-
});
|
|
75
|
-
if(r.status >= 300) {
|
|
76
|
-
throw new Error(await r.text());
|
|
77
|
-
}
|
|
78
|
-
const text = await r.text();
|
|
79
|
-
try {
|
|
80
|
-
const rs = JSON.parse(text);
|
|
81
|
-
if (rs.success) {
|
|
82
|
-
const redirectUrl = rs?.data?.instrumentResponse?.redirectInfo?.url;
|
|
83
|
-
if (redirectUrl) {
|
|
84
|
-
return this.redirect(redirectUrl);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
throw new Error("Failed");
|
|
88
|
-
} catch (error) {
|
|
89
|
-
throw new Error(text);
|
|
90
|
-
}
|
|
16
|
+
const pr = await this.gateway.createPaymentLink({ itemID, currency, host, testMode: this.query.test });
|
|
17
|
+
return this.redirect(pr.url);
|
|
91
18
|
}
|
|
92
19
|
}
|
|
93
20
|
|
|
94
|
-
function signRequest(id: any, salt: any, payload: string, path = "/pg/v1/pay"): { request: any; verify: any; } {
|
|
95
|
-
const request = Buffer.from(payload, "utf-8").toString("base64");
|
|
96
|
-
const signPayload = `${request}${path}${salt}`;
|
|
97
|
-
const sha256 = createHash("sha256").update(signPayload).digest("hex");
|
|
98
|
-
return {
|
|
99
|
-
request,
|
|
100
|
-
verify: `${sha256}###${id}`
|
|
101
|
-
};
|
|
102
|
-
}
|